{"record":{"id":"ad8d4f2e204c1c0f","repo":"HeyPuter/puter","slug":"not-found-ad8d4f","errorCode":"not_found","errorMessage":"Entry not found","messagePattern":"Entry not found","errorType":"exception","errorClass":"HttpError","httpStatus":404,"severity":"error","filePath":"src/backend/controllers/fs/FSController.ts","lineNumber":1643,"sourceCode":"                rawPath !== undefined\n                    ? mod.expandTildePath(rawPath, username)\n                    : undefined,\n            uid:\n                typeof source.uid === 'string'\n                    ? source.uid\n                    : typeof source.uuid === 'string'\n                      ? source.uuid\n                      : undefined,\n            id:\n                typeof source.id === 'number' || typeof source.id === 'string'\n                    ? source.id\n                    : undefined,\n        };\n        const entry = await mod.resolveNode(this.stores.fsEntry, ref, {\n            required: true,\n        });\n        if (!entry) {\n            throw new HttpError(404, 'Entry not found', {\n                legacyCode: 'not_found',\n            });\n        }\n        return entry;\n    }\n\n    /**\n     * Authorize creation of a new entry at `targetPath`. The standard rule is\n     * write on the parent, but we also accept write on the target itself — this\n     * lets an app create its own `/<user>/AppData/<app_uid>` folder (parent\n     * `AppData` is off-limits, but the target is the app's own subtree per\n     * ACLService's short-circuit) and lets recipients of a direct share on a\n     * not-yet-existent path materialize it.\n     */\n    async #assertCanCreate(actor: Actor, targetPath: string) {\n        const parent = pathPosix.dirname(targetPath);\n        const parentForCheck = parent === '/' ? targetPath : parent;\n        const fsService = this.services.fs;","sourceCodeStart":1625,"sourceCodeEnd":1661,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/controllers/fs/FSController.ts#L1625-L1661","documentation":"Thrown by FSController.#resolveEntryForRequest when `resolveNode(..., { required: true })` returns null/undefined for a `parent` or `target` reference. The controller builds a ref from `path`, `uid`/`uuid`, or `id`, asks the fsEntry store to resolve it, and 404s if nothing matched. This guards every operation that derefs a node ref (mkshortcut parent/target, copy source/dest, etc.).","triggerScenarios":"POST /mkshortcut with a `parent`/`target` whose path doesn't exist, was deleted, belongs to another user without share, or whose uid/uuid/id is wrong. Passing a uid that was rotated or an id from a different shard. A race where the entry was deleted between listing and the mutate call.","commonSituations":"Stale cached uid/uuid on the client after a move/rename; using a path under another user's home without a share grant; copy-pasting a fragment of a uid; referring to an entry by `id` when the column type changed.","solutions":["Re-resolve the ref against the source of truth (stat/readdir) and resend with the corrected path/uid/id.","Prefer uid/uuid over path if the entry may have been renamed between calls.","If the entry should be shared with the actor, confirm the share record exists and grants at least `see`.","Handle 404 gracefully in the client and refresh the file listing rather than retrying blindly."],"exampleFix":"// before\n{ target: { uid: staleUid } }\n// after\nconst fresh = await puter.fs.stat(targetPath);\n{ target: { uid: fresh.uid } }","handlingStrategy":"validation","validationCode":"async function resolveEntry(ref) {\n  const entry = await puter.fs.stat(ref.path ?? ref.uid ?? ref.id);\n  if (!entry) throw new Error(`Entry not found: ${JSON.stringify(ref)}`);\n  return entry;\n}","typeGuard":"/** @param {unknown} r */\nfunction isNodeRef(r) {\n  return !!r && typeof r === 'object' && ('path' in r || 'uid' in r || 'uuid' in r || 'id' in r);\n}","tryCatchPattern":"try { await op(); }\ncatch (e) {\n  if (e?.status === 404) { /* refresh listing, mark node stale */ }\n  else throw e;\n}","preventionTips":["Prefer uid/uuid over path when the entry may be renamed.","Stat the entry before mutating if there's any chance it was deleted.","Treat 404 as authoritative and refresh rather than blind-retry."],"tags":["fs","not-found","api","node-ref"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}