{"record":{"id":"6d154edf140e44fa","repo":"n8n-io/n8n","slug":"run-this-runid-is-not-suspended-cannot-resume","errorCode":null,"errorMessage":"Run ${this.runId} is not suspended. Cannot resume.","messagePattern":"Run (.+?) is not suspended\\. Cannot resume\\.","errorType":"exception","errorClass":"StaleResumeError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/agents/src/runtime/loop/agent-runtime.ts","lineNumber":426,"sourceCode":"\t\t\t\t\t`Cannot decrease maxIterations when resuming a run. Expected >= ${persistedMaxIterations}, received ${callerMaxIterations}.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst mergedMaxIterations = callerMaxIterations ?? persistedMaxIterations;\n\t\t\tconst mergedExecOptions: ExecutionOptions & { iterationCount?: number } = {\n\t\t\t\t...callerExecOptions,\n\t\t\t\t...(mergedMaxIterations !== undefined ? { maxIterations: mergedMaxIterations } : {}),\n\t\t\t\t...(state.iterationCount !== undefined ? { iterationCount: state.iterationCount } : {}),\n\t\t\t};\n\n\t\t\tconst resumeOptions: RuntimeExecutionOptions = {\n\t\t\t\tpersistence: state.persistence,\n\t\t\t\t...mergedExecOptions,\n\t\t\t};\n\n\t\t\tconst claimed = await this.runState.claimResume(this.runId, state);\n\t\t\tif (!claimed) {\n\t\t\t\tthrow new StaleResumeError(`Run ${this.runId} is not suspended. Cannot resume.`);\n\t\t\t}\n\t\t\tawait options.onResumeClaimed?.();\n\n\t\t\tabortScope = this.eventBus.createAbortScope(resumeOptions.abortSignal);\n\t\t\tconst activeAbortScope = abortScope;\n\n\t\t\tconst pendingResume: PendingResume = {\n\t\t\t\tpendingToolCalls: state.pendingToolCalls,\n\t\t\t\tresumeToolCallId: options.toolCallId,\n\t\t\t\tresumeData,\n\t\t\t};\n\n\t\t\tawait this.ensureModelCost();\n\n\t\t\tawait this.memory.setListObservationLogMemory(list, state.persistence);\n\n\t\t\tif (method === 'generate') {\n\t\t\t\tconst sink = new GenerateSink(this.createRunServices());","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/agents/src/runtime/loop/agent-runtime.ts#L408-L444","documentation":"Thrown by the memory-session-key validator when an AI memory subnode's session key expression uses $json. $json resolves to the current node's input, which is fragile and ambiguous for session keys — it can produce unstable or colliding sessions. The validator requires an explicit node reference so the key is deterministic.","triggerScenarios":"A session-key parameter value is a string that includes '$json' AND either starts with '=' or contains '{{'. The helper isUnsafeSessionExpression matches that shape, and createIssue is emitted for that parameter path.","commonSituations":"Wiring a memory subnode (Buffer/Window memory) and pointing the sessionId at {{$json.message.chat.id}}; an AI builder defaults to $json because it is the shortest reference; copying a Telegram-bot tutorial that used $json before this guard existed.","solutions":["Reference the trigger explicitly, e.g. nodeJson(trigger, 'message.chat.id').","Or use the full node reference form $('Trigger').item.json.message.chat.id.","Pin the session key to a stable upstream field that uniquely identifies the conversation/user."],"exampleFix":"// before\nmemory: windowBufferMemory({\n  sessionId: '={{ $json.message.chat.id }}',\n}),\n\n// after\nmemory: windowBufferMemory({\n  sessionId: expr(\"={{ $('Trigger').item.json.message.chat.id }}\"),\n});","handlingStrategy":"validation","validationCode":"function isUnsafeSessionExpression(value: unknown): value is string {\n  return typeof value === 'string' && value.includes('$json') && (value.startsWith('=') || value.includes('{{'));\n}\n\n// before assigning a session key:\nif (isUnsafeSessionExpression(sessionId)) {\n  throw new Error('Session key uses $json; use an explicit node reference like $(\\'Trigger\\').item.json.message.chat.id');\n}","typeGuard":"function isUnsafeSessionExpression(value: unknown): value is string {\n  return typeof value === 'string' && value.includes('$json') && (value.startsWith('=') || value.includes('{{'));\n}","tryCatchPattern":null,"preventionTips":["Always reference the trigger or a named upstream node for session keys.","Ban $json in session-key expressions in your generator's lint rules.","Pin the key to a stable conversation/user identifier."],"tags":["ai","langchain","memory","session-key","expressions"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}