{"record":{"id":"fe3c4a78f71f27e7","repo":"pbakaus/impeccable","slug":"unauthorized-fe3c4a","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"skill/scripts/live/manual-edit-routes.mjs","lineNumber":80,"sourceCode":"        }\n        const { totalCount, perPage } = countPendingByPage(projectCwd());\n        const pendingCount = perPage[msg.pageUrl] || 0;\n        recordManualEditActivity('manual_edit_stashed', {\n          id: msg.id,\n          pageUrl: msg.pageUrl,\n          opCount: msg.ops.length,\n          pendingCount,\n          totalCount,\n          hintedFileCount: new Set((msg.ops || []).map((op) => summarizeManualLogFile(op.sourceHint?.file, projectCwd())).filter(Boolean)).size,\n        });\n        sendJson(res, 200, { ok: true, pendingCount, totalCount, perPage });\n      });\n      return true;\n    }\n\n    if (p === '/manual-edit-stash' && req.method === 'GET') {\n      const token = url.searchParams.get('token');\n      if (token !== getToken()) { res.writeHead(401); res.end('Unauthorized'); return true; }\n      const pageUrl = url.searchParams.get('pageUrl') || '';\n      const { totalCount, perPage } = countPendingByPage(projectCwd());\n      const buffer = readManualEditsBuffer(projectCwd());\n      const entriesForPage = pageUrl ? buffer.entries.filter((e) => e.pageUrl === pageUrl) : buffer.entries;\n      sendJson(res, 200, {\n        count: pageUrl ? (perPage[pageUrl] || 0) : totalCount,\n        totalCount,\n        perPage,\n        entries: entriesForPage,\n      });\n      return true;\n    }\n\n    if (p === '/manual-edit-commit' && req.method === 'POST') {\n      const token = url.searchParams.get('token');\n      if (token !== getToken()) { res.writeHead(401); res.end('Unauthorized'); return true; }\n      const pageUrl = url.searchParams.get('pageUrl');\n      const asyncMode = /^(1|true|yes)$/i.test(url.searchParams.get('async') || '');","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/pbakaus/impeccable/blob/f88b2837a7d7c3182e46307bbbb091a1ed547571/skill/scripts/live/manual-edit-routes.mjs#L62-L98","documentation":"GET /manual-edit-stash on the impeccable live server returns the pending manual-edit buffer (count, perPage, entries filtered by pageUrl). It is gated by a per-server-instance token: the token query parameter must string-equal the server's current token (generated at startup and recorded in its server.json). A bare writeHead(401) 'Unauthorized' is returned on mismatch or omission.","triggerScenarios":"Calling /manual-edit-stash without ?token=; using a token captured from a previous server run after the server restarted (tokens rotate per instance); hitting the wrong port so a different server's token is compared.","commonSituations":"Server restarted while an old browser tab kept polling with the embedded old TOKEN; curl scripts with a hardcoded token; page loaded from cache after server death and rebirth.","solutions":["Read the current token from the live server's output/session (server.json records port + token) and re-issue the request with ?token=","Reload the target page after any server restart so the injected client re-fetches live.js with the fresh token","Confirm the port matches the running server instance"],"exampleFix":"# before\ncurl 'http://localhost:4173/manual-edit-stash?pageUrl=/'\n# after\ncurl \"http://localhost:4173/manual-edit-stash?token=$TOKEN&pageUrl=/\"","handlingStrategy":"retry","validationCode":"// Validate request preconditions before polling\nconst token = readTokenFromSession(); // server.json: port + token\nif (!token) throw new Error('no live-server token — is the server running?');\nconst url = `http://localhost:${PORT}/manual-edit-stash?token=${encodeURIComponent(token)}`;","typeGuard":null,"tryCatchPattern":"let res = await fetch(url);\nif (res.status === 401) {\n  TOKEN = readTokenFromSession(); // token rotated after restart\n  res = await fetch(urlWithNewToken); // single retry\n}","preventionTips":["Read port + token from the server session file at call time, never hardcode","After restarting the live server, reload the target page before scripting against its routes","A 401 means token mismatch, not server death — refresh the token rather than rebooting everything"],"tags":["auth","token","manual-edit","http-401","dev-server"],"backgroundTag":"unauthorized-invalid-token","analyzedSha":"f88b2837a7d7c3182e46307bbbb091a1ed547571","analyzedAt":"2026-08-18T04:58:36.608Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}