{"record":{"id":"3c4d4b1d014bc1e1","repo":"nanocoai/nanoclaw","slug":"inbox-safety-failed-to-resolve-inbox-dir","errorCode":null,"errorMessage":"inbox-safety: failed to resolve inbox dir","messagePattern":"inbox-safety: failed to resolve inbox dir","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/inbox-safety.ts","lineNumber":80,"sourceCode":"        return null;\n      }\n    } catch {\n      // Does not exist yet — fine, mkdir below creates it.\n    }\n  }\n\n  fs.mkdirSync(inboxDir, { recursive: true });\n\n  try {\n    const realInboxDir = fs.realpathSync(inboxDir);\n    const realInboxRoot = fs.realpathSync(inboxRoot);\n    if (!isPathInside(realInboxRoot, realInboxDir)) {\n      log.warn('inbox-safety: inbox dir escaped inbox root', { ...context, inboxDir });\n      return null;\n    }\n    return realInboxDir;\n  } catch (err) {\n    log.warn('inbox-safety: failed to resolve inbox dir', { ...context, inboxDir, err });\n    return null;\n  }\n}\n","sourceCodeStart":62,"sourceCodeEnd":84,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/inbox-safety.ts#L62-L84","documentation":"Resolving/realpath-ing an intended inbox directory threw — e.g. a parent disappeared mid-resolution (ENOENT on realpath), permission denied, or a symlink loop. The operation returns null and the caller treats the inbox path as unusable (attachment extraction is skipped).","triggerScenarios":"ensureContainedInboxDir's fs.realpath calls throw on a missing/renamed session dir, an unreadable parent, or a symlinked path segment.","commonSituations":"Session directory recreated concurrently (container restart race), permission changes on data/v2-sessions, or symlinked data dirs.","solutions":["Check the inboxDir in the log exists and all parents are traversable (x bit)","Avoid symlinks in the data/ tree","Retry the attachment send — transient races usually clear"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\nconst p = fs.realpathSync(inboxDir); // pre-validate before extracting attachments\nif (!p.startsWith(realInboxRoot)) abort();","typeGuard":"function isSafeInboxDir(dir: string, root: string): boolean {\n  try { return fs.realpathSync(dir).startsWith(fs.realpathSync(root) + '/'); } catch { return false; }\n}","tryCatchPattern":"const safe = ensureContainedInboxDir(dir); if (!safe) skipAttachmentExtraction();","preventionTips":["Keep data/v2-sessions on a real (non-symlinked) local path","Don't delete/recreate session dirs while messages flow","Retry attachment sends after transient races"],"tags":["filesystem","attachments","inbox","path-safety"],"backgroundTag":"realpath-resolution-failed","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}