multica-ai/multica · error
runtime profile is disabled
Error message
runtime profile is disabled
What it means
errRuntimeProfileDisabled is the sentinel returned by upsertRuntimeWithProfile when a daemon tries to register (upsert) a custom runtime against a runtime profile that has been disabled. Registration is serialized with profile deletion via row locks (the profile row holds a KEY SHARE lock until the upsert commits), so this error means the profile was found but is not in an enabled state — the daemon cannot bring up an instance for it. Callers match on this sentinel to return a distinct 'profile disabled' response rather than a generic failure.
Source
Thrown at server/internal/handler/daemon.go:312
})
if err != nil {
return rt
}
shared, ok := sharedDaemonCustomName(names)
if !ok {
return rt
}
updated, err := h.Queries.UpdateAgentRuntimeCustomName(ctx, db.UpdateAgentRuntimeCustomNameParams{
CustomName: pgtype.Text{String: shared, Valid: true},
ID: rt.ID,
})
if err != nil {
return rt
}
return updated
}
var errRuntimeProfileDisabled = errors.New("runtime profile is disabled")
// upsertRuntimeWithProfile serializes custom-runtime registration with profile
// deletion. The profile row remains KEY SHARE locked until the runtime upsert
// commits; DeleteRuntimeProfile takes a conflicting UPDATE lock before it
// enumerates runtime rows. This closes the stale-read window where deletion
// could miss an instance inserted by a concurrently registering daemon.
func (h *Handler) upsertRuntimeWithProfile(
ctx context.Context,
workspaceID, profileID pgtype.UUID,
build func(db.RuntimeProfile) db.UpsertAgentRuntimeWithProfileParams,
) (db.UpsertAgentRuntimeWithProfileRow, db.RuntimeProfile, error) {
var row db.UpsertAgentRuntimeWithProfileRow
var profile db.RuntimeProfile
tx, err := h.TxStarter.Begin(ctx)
if err != nil {
return row, profile, fmt.Errorf("begin profile runtime registration: %w", err)
}View on GitHub (pinned to 2c0912b6ec)
Solutions
- On the daemon, stop retrying registration for that profileID and mark it locally disabled until the profile list refreshes.
- Re-fetch the workspace's runtime profile list and drop profiles not enabled.
- If the disable was unintentional, re-enable the profile server-side and registration will succeed on the next heartbeat.
- Surface the 'profile disabled' distinction to operators instead of logging it as a generic registration failure.
Example fix
// before
for {
err := registerRuntime(ctx, profileID)
if err != nil { time.Sleep(retryInterval) } // blind retry loop
}
// after
err := registerRuntime(ctx, profileID)
if errors.Is(err, errRuntimeProfileDisabled) {
localProfiles.disable(profileID) // stop retrying; wait for profile refresh
return
} Defensive patterns
Strategy: try-catch
Try / catch
err := h.upsertRuntimeWithProfile(ctx, workspaceID, profileID, build)
if err != nil {
if errors.Is(err, errRuntimeProfileDisabled) {
// profile was disabled between listing and registration:
// stop retrying this profileID, mark it dead locally,
// and wait for the next profile list refresh
daemon.markProfileDisabled(profileID)
return nil
}
return fmt.Errorf("register runtime: %w", err)
} Prevention
- Match with errors.Is against the sentinel — do not string-compare the message.
- Refresh the profile list before registration attempts after any disable/delete event.
- Distinguish this from transient errors in daemon logs; it is terminal per-profile, not retryable.
- On the server side, keep returning this sentinel (not a generic 500) so clients can react precisely.
When it happens
Trigger: Daemon heartbeat/register call (PUT or upsert runtime) for a profileID whose profile row exists but is disabled — typically right after an admin disables the profile, or while a DeleteRuntimeProfile is racing the registration (the lock ordering closes the stale-read window, so the daemon gets a clean 'disabled' instead of registering a doomed instance).
Common situations: Admin disables a runtime profile while daemons are still running and auto-registering on heartbeat; a daemon caching an old profile list and retrying registration against a since-disabled profile; rollout flow where profiles are disabled before deletion and lagging daemons hit the window.
Related errors
- cloud runtime fleet URL is not configured
- repo is not configured for this workspace
- ErrRepoBusy
- acquire advisory lock %d: %w
- acquire advisory-lock connection: %w
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/663b4c51d40405a5.
Report an issue: GitHub.