{"record":{"id":"0f6bc63ca7632a0f","repo":"TencentCloud/TencentDB-Agent-Memory","slug":"generation-log-object-key-exceeds-cos-limit","errorCode":null,"errorMessage":"Generation log object key exceeds COS limit","messagePattern":"Generation log object key exceeds COS limit","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"MemoryCore/src/core/memory-generation-log/store.ts","lineNumber":45,"sourceCode":"}\n\nfunction reverseTimestamp(timestampMs: number): string {\n  return String(MAX_TS - timestampMs).padStart(13, \"0\");\n}\n\nexport function buildGenerationLogIdentity(\n  layer: MemoryGenerationLayer,\n  finishedAtMs: number,\n  anchorMemoryId?: string,\n  status: MemoryGenerationStatus = \"succeeded\",\n): { generationId: string; logId: string; key: string } {\n  const generationId = `mg_${randomUUID().replace(/-/g, \"\")}`;\n  const anchor = safeId(anchorMemoryId ?? \"none\");\n  const suffix = generationId.slice(3, 19);\n  const logId = `mgl_${layer}_${status}_${finishedAtMs}_${anchor}_${suffix}`;\n  const { date, hour } = utcParts(finishedAtMs);\n  const key = `${ROOT}/layer=${layer}/date=${date}/hour=${hour}/${reverseTimestamp(finishedAtMs)}__mid=${anchor}__lid=${logId}.json`;\n  if (Buffer.byteLength(key, \"utf8\") > 850) throw new Error(\"Generation log object key exceeds COS limit\");\n  return { generationId, logId, key };\n}\n\nexport function buildPromptGenerationRef(\n  resolved: ResolvedMemoryPrompt | undefined,\n  layer: MemoryGenerationLayer,\n): MemoryGenerationLog[\"prompt\"] {\n  if (!resolved) {\n    return { memory_prompt_id: `builtin:${layer}`, version: 1, source: \"system\", prompt_sha256: \"\" };\n  }\n  return {\n    memory_prompt_id: resolved.memory_prompt_id,\n    version: resolved.version,\n    source: resolved.source,\n    prompt_sha256: createHash(\"sha256\").update(resolved.prompt).digest(\"hex\"),\n  };\n}\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/3efcd317b84146d6a08518ac0f7ee7c8a8d200ec/MemoryCore/src/core/memory-generation-log/store.ts#L27-L63","documentation":"buildGenerationLogIdentity builds a COS object key embedding layer, timestamp, anchor memory id and log id, then enforces a hard 850-byte UTF-8 limit on the key because object stores (Tencent COS) cap key length. This guard throws when the composed key would exceed that limit.","triggerScenarios":"Calling buildGenerationLogIdentity (directly or via l2Identity, l3Identity, generationIdentity) where the resulting key string exceeds 850 bytes — practically caused by an extremely long anchorMemoryId, since layer/date/hour/logId segments are fixed-length.","commonSituations":"anchorMemoryId is not a short id but a long URL, full text, or concatenated identifiers passed in as the anchor; passing raw uuid-ish strings plus extra prefixes; upstream refactor started passing a composite anchor string.","solutions":["Pass a short, bounded anchorMemoryId (a real memory id) — the code already runs it through safeId, so check what safeId permits and pre-truncate/hash long identifiers before calling","Hash or truncate the anchor (e.g. first 32 chars of a sha256) at the call site if the id is genuinely long","Investigate why an oversized id reached this code path; the limit triggers only with pathological input"],"exampleFix":"// before\nconst key = buildGenerationLogIdentity({ layer: \"l2\", status: \"ok\", anchorMemoryId: longCompositeId });\n// after\nconst anchor = createHash(\"sha256\").update(longCompositeId).digest(\"hex\").slice(0, 32);\nconst key = buildGenerationLogIdentity({ layer: \"l2\", status: \"ok\", anchorMemoryId: anchor });","handlingStrategy":"validation","validationCode":"function safeAnchorId(id, max = 64) {\n  return Buffer.byteLength(String(id), \"utf8\") <= max ? id : createHash(\"sha256\").update(String(id)).digest(\"hex\").slice(0, 32);\n}","typeGuard":"function isBoundedAnchorId(id) {\n  return typeof id === \"string\" && id.length > 0 && Buffer.byteLength(id, \"utf8\") <= 64;\n}","tryCatchPattern":"try {\n  const identity = buildGenerationLogIdentity(args);\n} catch (e) {\n  if (e.message.includes(\"exceeds COS limit\")) {\n    logger.error(\"anchorMemoryId too long; hash/truncate before calling\");\n  }\n  throw e;\n}","preventionTips":["Always pass short memory ids (not URLs, text, or composite strings) as anchorMemoryId","Hash long identifiers before using them as anchors","Keep call-site helpers that normalize anchor ids in one place"],"tags":["storage","cos","validation","limit"],"backgroundTag":"object-key-too-long","analyzedSha":"3efcd317b84146d6a08518ac0f7ee7c8a8d200ec","analyzedAt":"2026-09-01T05:44:22.276Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}