{"record":{"id":"2512d4ec701af5c7","repo":"ruvnet/ruflo","slug":"session-not-found-sessionid","errorCode":null,"errorMessage":"Session not found: ${sessionId}","messagePattern":"Session not found: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/shared/src/core/orchestrator/session-manager.ts","lineNumber":127,"sourceCode":"    return this.sessions.get(sessionId);\n  }\n\n  getActiveSessions(): IAgentSession[] {\n    return Array.from(this.sessions.values()).filter(\n      session => session.status === 'active' || session.status === 'idle',\n    );\n  }\n\n  getSessionsByAgent(agentId: string): IAgentSession[] {\n    return Array.from(this.sessions.values()).filter(\n      session => session.agentId === agentId,\n    );\n  }\n\n  async terminateSession(sessionId: string): Promise<void> {\n    const session = this.sessions.get(sessionId);\n    if (!session) {\n      throw new Error(`Session not found: ${sessionId}`);\n    }\n\n    session.status = 'terminated';\n    session.endTime = new Date();\n\n    const duration = session.endTime.getTime() - session.startTime.getTime();\n\n    this.eventBus.emit(SystemEventTypes.SESSION_TERMINATED, {\n      sessionId,\n      agentId: session.agentId,\n      duration,\n    });\n\n    // Clean up profile reference\n    this.sessionProfiles.delete(sessionId);\n\n    // Persist sessions asynchronously\n    this.persistSessions().catch(() => {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/shared/src/core/orchestrator/session-manager.ts#L109-L145","documentation":"SessionManager.terminateSession() looks the session up in an in-memory Map and throws when sessionId is absent. Sessions are created by createSession() (which assigns a generated secure ID) and tracked per manager instance, so unknown, already-terminated-but-removed, or cross-instance IDs fail here.","triggerScenarios":"Calling terminateSession() with an ID not returned by createSession(); terminating the same session twice in cleanup paths; passing an ID obtained from getSessionsByAgent() of a different SessionManager instance.","commonSituations":"Logout/cleanup code that runs twice; session IDs persisted to disk (sessions.json) and reused after the process restarted with an empty in-memory map; multi-worker setups where each worker has its own SessionManager.","solutions":["Check sessionManager.getSession(sessionId) before terminating; treat undefined as already gone","Make teardown idempotent by catching and ignoring 'Session not found'","When restoring persisted sessions after restart, re-register them before allowing terminateSession calls"],"exampleFix":"// before\nawait sessionManager.terminateSession(sessionId);\n\n// after\nif (sessionManager.getSession(sessionId)) {\n  await sessionManager.terminateSession(sessionId);\n}","handlingStrategy":"validation","validationCode":"if (sessionManager.getSession(sessionId)?.status === 'active') {\n  await sessionManager.terminateSession(sessionId);\n}","typeGuard":"const session = sessionManager.getSession(sessionId);\nif (session) {\n  // safe to terminate\n}","tryCatchPattern":"try {\n  await sessionManager.terminateSession(sessionId);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Session not found')) return;\n  throw e;\n}","preventionTips":["Check getSession() before terminating","Never assume persisted session IDs survive a process restart — the in-memory map starts empty","Make cleanup paths idempotent"],"tags":["session","not-found","orchestrator"],"backgroundTag":"entity-not-found","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}