{"record":{"id":"20302282211e3bee","repo":"paperclipai/paperclip","slug":"decision-signing-key-at-keypath-must-be-a-regul","errorCode":null,"errorMessage":"Decision signing key at ${keyPath} must be a regular file","messagePattern":"Decision signing key at (.+?) must be a regular file","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/decision-signing.ts","lineNumber":25,"sourceCode":"const MIN_SECRET_LENGTH = 32;\n\nfunction resolveGeneratedSecretFilePath() {\n  return path.join(path.dirname(resolveDefaultSecretsKeyFilePath()), \"decision-signing.key\");\n}\n\nfunction assertOwnedByCurrentUser(stats: Stats, description: string) {\n  if (process.platform === \"win32\") return;\n\n  const currentUserId = process.getuid?.();\n  if (currentUserId !== undefined && stats.uid !== currentUserId) {\n    throw new Error(`${description} must be owned by the Paperclip process user`);\n  }\n}\n\nfunction enforceKeyFilePermissions(keyPath: string) {\n  let stats = lstatSync(keyPath);\n  if (!stats.isFile()) {\n    throw new Error(`Decision signing key at ${keyPath} must be a regular file`);\n  }\n  assertOwnedByCurrentUser(stats, `Decision signing key at ${keyPath}`);\n  if (process.platform === \"win32\") return;\n\n  const mode = stats.mode & 0o777;\n  if ((mode & 0o077) !== 0) {\n    chmodSync(keyPath, 0o600);\n    stats = lstatSync(keyPath);\n    if (!stats.isFile()) {\n      throw new Error(`Decision signing key at ${keyPath} must be a regular file`);\n    }\n    assertOwnedByCurrentUser(stats, `Decision signing key at ${keyPath}`);\n    if ((stats.mode & 0o077) !== 0) {\n      throw new Error(`Decision signing key at ${keyPath} must have permissions 0600`);\n    }\n  }\n}\n","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/paperclipai/paperclip/blob/120ae5428fa29bee300bcf806491cd4d965fbb7c/server/src/services/decision-signing.ts#L7-L43","documentation":"Filetype guard in enforceKeyFilePermissions: lstat shows the decision-signing key path is not a regular file (symlink, directory, device, etc.). Secret material must be a plain file so ownership/permission checks are meaningful; re-checked again after a chmod attempt.","triggerScenarios":"Thrown at server/src/services/decision-signing.ts:25 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure the decision signing key path points to a regular file, not a directory or symlink."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"120ae5428fa29bee300bcf806491cd4d965fbb7c","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}