{"record":{"id":"d2c2fad5ef5ea6c0","repo":"mastra-ai/mastra","slug":"invalid-handle","errorCode":"invalid-handle","errorMessage":"Knowledge record handle is invalid or expired.","messagePattern":"Knowledge record handle is invalid or expired\\.","errorType":"error_code","errorClass":"KnowledgeInspectorError","httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/knowledge-inspector.ts","lineNumber":689,"sourceCode":"    type: KnowledgeInspectorRecordType,\n    recordId: string,\n  ): string {\n    this.#pruneOpaqueEntries();\n    const token = opaqueToken();\n    this.#handles.set(token, {\n      identityKey: binding.identityKey,\n      level,\n      type,\n      recordId,\n      expiresAt: Date.now() + HANDLE_TTL_MS,\n    });\n    return token;\n  }\n\n  #readHandle(handle: string, binding: Binding, expectedType: KnowledgeInspectorRecordType): HandleEntry {\n    const entry = this.#handles.get(handle);\n    if (!entry || entry.expiresAt < Date.now() || entry.type !== expectedType) {\n      throw new KnowledgeInspectorError('invalid-handle', 'Knowledge record handle is invalid or expired.');\n    }\n    if (entry.identityKey !== binding.identityKey) {\n      throw new KnowledgeInspectorError('stale-handle', 'Knowledge record handle belongs to a previous scope.');\n    }\n    return entry;\n  }\n\n  #mintCursor(\n    binding: Binding,\n    level: KnowledgeInspectorScopeLevel,\n    kind: CursorEntry['kind'],\n    value: string,\n    filters?: CursorEntry['filters'],\n  ): string {\n    this.#pruneOpaqueEntries();\n    const token = opaqueToken();\n    this.#cursors.set(token, {\n      identityKey: binding.identityKey,","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/knowledge-inspector.ts#L671-L707","documentation":"Knowledge record handles are opaque in-memory tokens with a TTL (HANDLE_TTL_MS) and an expected record type. #readHandle() throws 'invalid-handle' when the token is unknown, expired (pruned after expiresAt), evicted by the MAX_OPAQUE_ENTRIES cap, or used with the wrong expectedType (e.g. a node handle passed where an event handle is expected).","triggerScenarios":"Calling a read/detail API with: a handle minted by a different inspector instance, a handle older than the TTL, a handle after the inspector's scope changed (handles cleared), or a node handle where an event/activity handle type is required.","commonSituations":"Storing handles long-term (persisting them across restarts); app idle longer than the TTL; holding many handles so the size cap evicts older ones; copy-pasting a handle into the wrong API.","solutions":["Re-list or re-query to mint a fresh handle instead of reusing an old one.","Use handles promptly after they are returned; treat them as short-lived opaque tokens, never persist them.","Catch KnowledgeInspectorError code 'invalid-handle', refresh the listing, and retry once with the new handle."],"exampleFix":"// before\nconst savedHandle = fs.readFileSync('handle.txt', 'utf8'); // persisted across runs\nawait inspector.getNode(savedHandle);\n// after\nconst { entries } = await inspector.listNodes({ level: 'resource' });\nawait inspector.getNode(entries[0].handle); // fresh handle from current binding","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await inspector.getNode(handle);\n} catch (e) {\n  if (e instanceof KnowledgeInspectorError && e.code === 'invalid-handle') {\n    const { entries } = await inspector.listNodes({ level });\n    return entries.find(n => n.name === lastName) ?? null; // refresh and re-locate\n  }\n  throw e;\n}","preventionTips":["Treat handles as ephemeral: use immediately, never persist to disk or DB.","Refresh listings rather than caching handles across idle periods (TTL-bounded).","Pass the correct handle type to each API (node handle for node reads, event handle for activity reads)."],"tags":["knowledge-inspector","expired-token","opaque-handle"],"backgroundTag":"expired-opaque-token","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}