{"record":{"id":"246d44f86ce4842a","repo":"block/buzz","slug":"this-agent-is-present-on-the-relay-starting-anoth-246d44","errorCode":null,"errorMessage":"This agent is present on the relay. Starting another instance is unavailable.","messagePattern":"This agent is present on the relay\\. Starting another instance is unavailable\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"desktop/src/features/channels/ui/useMembersSidebarActions.ts","lineNumber":73,"sourceCode":"export function useMembersSidebarActions({\n  channelId,\n  getAvailability,\n  controllableManagedBots,\n  removableManagedBots,\n  currentPubkey,\n  onOpenChange,\n  relayUrl,\n}: UseMembersSidebarActionsOptions) {\n  const queryClient = useQueryClient();\n  function assertStartNotBlockedByPresence(\n    agent: ManagedAgent,\n    lifecycleActive: boolean,\n  ) {\n    const reason = agentPresenceStartBlockReason(\n      lifecycleActive,\n      getAvailability(agent.pubkey),\n    );\n    if (reason) throw new Error(reason);\n  }\n  const removeMemberMutation = useRemoveChannelMemberMutation(channelId);\n  const startManagedAgentMutation = useStartManagedAgentMutation();\n  const stopManagedAgentMutation = useStopManagedAgentMutation();\n  const runtimeActionMutation = useManagedAgentRuntimeAction();\n  const [actionNoticeMessage, setActionNoticeMessage] = React.useState<\n    string | null\n  >(null);\n  const [actionErrorMessage, setActionErrorMessage] = React.useState<\n    string | null\n  >(null);\n  const [activeActionKey, setActiveActionKey] = React.useState<string | null>(\n    null,\n  );\n\n  const stoppableManagedBots = React.useMemo(\n    () =>\n      controllableManagedBots.filter((agent) => isManagedAgentActive(agent)),","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/block/buzz/blob/dad5a33865fc81a2e55b3b60746632f615ec1e3a/desktop/src/features/channels/ui/useMembersSidebarActions.ts#L55-L91","documentation":"Same family as error 0: useMembersSidebarActions' assertStartNotBlockedByPresence throws when starting an agent from the channel members sidebar whose pubkey reports online/away relay presence. It guards both handleLifecycleAction and handleRespawnAll so the UI never spawns a duplicate agent body for an identity the relay already sees as present.","triggerScenarios":"Invoking a start/respawn lifecycle action from the members sidebar for a channel member whose normalized pubkey is in the presence snapshot with status 'online' or 'away', while the local lifecycle state is inactive.","commonSituations":"Respawning all channel agents when one is already running on another machine; starting a shared/relay-deployed agent owned elsewhere; presence snapshot hasn't caught up after someone else stopped the agent.","solutions":["Stop the running instance wherever it lives, wait for presence to report offline, then retry the sidebar action.","Confirm the presence snapshot is fresh (app connected, presence query settled) before retrying.","For respawn-all, exclude or skip agents whose availability is online/away instead of failing the whole batch.","If presence is stale (agent confirmed dead), refresh presence/agent caches and retry."],"exampleFix":"// before\nawait startManagedAgentMutation.mutateAsync(agent.id);\n\n// after\nconst reason = agentPresenceStartBlockReason(lifecycleActive, getAvailability(agent.pubkey));\nif (reason) {\n  setActionNoticeMessage(reason);\n  return;\n}\nawait startManagedAgentMutation.mutateAsync(agent.id);","handlingStrategy":"validation","validationCode":"const reason = agentPresenceStartBlockReason(lifecycleActive, getAvailability(agent.pubkey));\nif (reason) setActionNoticeMessage(reason); else void runLifecycleAction();","typeGuard":"const startable = (agent: ManagedAgent, active: boolean): boolean =>\n  !agentPresenceStartBlockReason(active, getAvailability(agent.pubkey));","tryCatchPattern":"try {\n  await handleLifecycleAction(agent);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"present on the relay\")) {\n    setActionNoticeMessage(\"Already running on the relay — stop the other instance first.\");\n    return;\n  }\n  throw e;\n}","preventionTips":["Guard member action menus with the same presence check used by the thrower.","For respawn-all flows, pre-filter agents whose availability is online/away.","Keep the presence snapshot connected and refreshed; disable actions during degraded state.","Never rely on local inactive state alone — always consult relay presence."],"tags":["presence","relay","channels","agents"],"backgroundTag":"agent-already-present-on-relay","analyzedSha":"dad5a33865fc81a2e55b3b60746632f615ec1e3a","analyzedAt":"2026-09-05T18:13:50.666Z","contentChangedAt":"2026-09-05T18:13:50.666Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}