Azure / Azure/azure-functions-host

Foreground SyncTriggers publish trigger metadata but never update the hash blob, breaking self-heal

Open Beginner friendly
#11,875 0 comments 0 reactions 0 assignees View on GitHub
Needs: Triage (Functions)
Dominant language
C#
Stars
2k
Forks
482
Avg merge
2d 10h
Merged PRs (30d)
36

Description

Split out from #11873 (suggested fix **#2**).

### Summary

`FunctionsSyncManager.TrySyncTriggersAsync` only reads and writes the SyncTriggers hash blob (`synctriggers/{hostId}/last`) when `isBackgroundSync == true`. **Foreground** syncs — inbound `/admin/host/synctriggers` requests — call `SetTriggersAsync` and publish the trigger payload to the platform, but they **never check, update, or invalidate the hash blob**. This leaves the hash blob out of sync with what was actually last published, which defeats the background-sync self-heal mechanism.

### Details

In `TrySyncTriggersAsync` ([`FunctionsSyncManager.cs`](https://github.com/Azure/azure-functions-host/blob/dev/src/WebJobs.Script.WebHost/Management/FunctionsSyncManager.cs#L99-L160)):

- The hash is only consulted when `isBackgroundSync` is `true`:
```csharp
bool shouldSyncTriggers = true;
string newHash = null;
if (isBackgroundSync && hashBlobClient != null)
{
newHash = await CheckHashAsync(hashBlobClient, payload.Content);
shouldSyncTriggers = newHash != null;
}

if (shouldSyncTriggers)
{
var (success, error) = await SetTriggersAsync(payload.Content);
if (success && newHash != null) // newHash is always null for foreground syncs
{
await UpdateHashAsync(hashBlobClient, newHash);
}
...
}
```
- For a foreground sync, `newHash` stays `null`, so `SetTriggersAsync` publishes the payload but `UpdateHashAsync` is never called.

### Why this is a bug

Because a foreground sync can publish a payload that differs from the hash currently stored in the blob, the blob no longer reflects the last-published trigger metadata. A subsequent **background** sync recomputes the current hash, finds it *matches* the (now-stale) blob, concludes "nothing changed," and **suppresses the corrective re-publish** — even though the live platform view is wrong.

This is the mechanism that wedges an app on the placeholder `WarmUp` payload in #11873:

1. A healthy **background** sync writes the *real-functions* hash to the blob.
2. A bad **foreground** `WarmUp` publish overwrites the live trigger payload but leaves the blob unchanged (still the real-functions hash).
3. The host recovers, recomputes the real-functions hash, compares to the blob → **they match** → background sync suppresses the re-publish.

Result: the platform stays on stale/incorrect trigger metadata until an external forced sync (portal Refresh, ARM `host/default/sync`, or another deploy) happens to re-publish.

### Proposed fix

Make foreground syncs keep the hash blob consistent with what they publish, so background self-heal can still detect drift. Two options:

- **Update** the hash blob after a successful foreground `SetTriggersAsync` (compute and store the published payload's hash), or
- **Invalidate/delete** the hash blob on foreground publish, forcing the next background sync to re-publish.

Updating is preferable to invalidating so we don't trigger an unnecessary extra publish, but either restores the self-heal guarantee that the blob always reflects the last-published payload.

### Related

- #11873 (parent — placeholder `WarmUp` stuck state)
- #10169
- https://github.com/Azure/functions-action/issues/245

Contributor guide

Open the contributing guide

Research direction

Start in src/WebJobs.Script.WebHost/Management/FunctionsSyncManager.cs, especially TrySyncTriggersAsync and its foreground SetTriggersAsync path. Trace how the hash blob is checked and updated, then verify that a successful foreground publish leaves the blob consistent with the published payload so a later background sync can detect drift.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, csharp
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.