{"record":{"id":"9e545fcb095c0cef","repo":"TencentCloud/TencentDB-Agent-Memory","slug":"skillcoreerror-rethrow-with-translated-code-messa","errorCode":null,"errorMessage":"SkillCoreError rethrow with translated code (message preserved from lower layer)","messagePattern":"SkillCoreError rethrow with translated code \\(message preserved from lower layer\\)","errorType":"error_code","errorClass":"SkillCoreError","httpStatus":null,"severity":"error","filePath":"MemoryCore/src/core/skill/skill-core.ts","lineNumber":87,"sourceCode":"  | \"STORAGE_NOT_FOUND\"\n  | \"LLM_UNAVAILABLE\"\n  | \"SKILL_COS_REQUIRED\"\n  | \"SKILL_EXPORT_TOO_LARGE\";\n\nexport class SkillCoreError extends Error {\n  constructor(public readonly code: SkillCoreErrorCode, message?: string) {\n    super(message ? `${code}: ${message}` : code);\n    this.name = \"SkillCoreError\";\n  }\n}\n\n// 工具：把下层抛的各类错误统一翻译为 SkillCoreError（保留原 message）\nfunction toCoreError(e: unknown): never {\n  if (e instanceof SkillCoreError) throw e;\n  const code = (e as { code?: string }).code as SkillCoreErrorCode | undefined;\n  const msg = (e as Error).message;\n  if (code) {\n    throw new SkillCoreError(code, msg);\n  }\n  throw e as Error;\n}\n\n// ═════════════════════════════════════════════════════════════════════\n//  Options\n// ═════════════════════════════════════════════════════════════════════\n\nexport interface SkillCoreOptions {\n  store: ISkillStore;\n  resources: SkillResourceStore;\n  versioning: SkillVersioning;\n  /**\n   * 用于 skill_id 生成。默认 `skl-` + 12 字符 base62（CSPRNG，71 bit 真熵）。\n   * 保持与老 sid 相同长度 (16 字符)，仅字符集从 base36 扩到 base62 且用真随机源。\n   * 测试可注入固定值。\n   */\n  ulid?: () => string;","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/3efcd317b84146d6a08518ac0f7ee7c8a8d200ec/MemoryCore/src/core/skill/skill-core.ts#L69-L105","documentation":"toCoreError is the SkillCore error-translation boundary: any error thrown by a lower layer (store, versioning, fs) that carries a \"code\" property is re-wrapped as a SkillCoreError with that code while preserving the original message. The generic message here describes that rethrow — you see the ORIGINAL lower-layer message inside a SkillCoreError wrapper, so the root cause is whatever message accompanies it.","triggerScenarios":"Any call into store/versioning from create, update, patch, writeFiles, or removeFiles that throws a coded, non-SkillCoreError — e.g. the persistence layer throwing {code: \"STORE_UNAVAILABLE\", message: ...} or an fs adapter with its own error codes.","commonSituations":"Backend store outages or constraint violations surfacing with their native codes; versioning layer rejecting appends; integration points where a dependency's error contract changed and its codes now map to a different SkillCoreErrorCode than before.","solutions":["Read the preserved message (and original code) in the thrown SkillCoreError to find the real lower-layer failure","Handle the specific SkillCoreErrorCode in your catch (e.g. retry on transient store errors, surface validation codes to callers)","If the code translation is wrong for your backend, fix the mapping in toCoreError or normalize codes at the adapter boundary","Log the original error stack before wrapping so the lower-layer origin is traceable"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// no pre-call validation applies; prepare classification for wrapped errors\nfunction unwrapSkillCoreError(e: unknown): { code?: string; message: string } | null {\n  if (e instanceof SkillCoreError) return { code: e.code, message: e.message };\n  return null;\n}","typeGuard":"function isSkillCoreError(e: unknown): e is SkillCoreError {\n  return e instanceof SkillCoreError && typeof e.code === \"string\";\n}","tryCatchPattern":"try {\n  await core.create(input);\n} catch (e) {\n  if (isSkillCoreError(e)) {\n    switch (e.code) {\n      case \"STORE_UNAVAILABLE\": return retryWithBackoff();\n      case \"INVALID_FRONTMATTER\": return reportValidation(e.message);\n      default: logger.error({ code: e.code, msg: e.message }, \"lower-layer failure surfaced via toCoreError\");\n    }\n  }\n  throw e;\n}","preventionTips":["Treat e.code on SkillCoreError as the authoritative lower-layer code and switch on it","Keep an inventory of codes your store/versioning adapters can emit","Log the original stack at the adapter boundary before wrapping","Add tests asserting each adapter error maps to the intended SkillCoreErrorCode"],"tags":["error-handling","rethrow","error-mapping"],"backgroundTag":"error-code-translation","analyzedSha":"3efcd317b84146d6a08518ac0f7ee7c8a8d200ec","analyzedAt":"2026-09-01T05:44:22.276Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}