fix: detect 404 from @kubernetes/client-node v1.x ApiException (FAR-85)

The v1.x ApiException exposes the HTTP status as `code`, not `statusCode`.
Both `isNotFound` (k8s-client) and `isK8s404` (execute) only checked
`statusCode`/`response.statusCode`, so 404s were never recognized:

- `getPvc` re-threw the 404 instead of returning null, which bubbled up
  through `ensureAgentDbPvc` as `k8s_job_create_failed` with the raw
  "persistentvolumeclaims X not found" body — the symptom in FAR-85.
- The PVC was never actually created, because the existence check threw
  before reaching `createPvc`.

Add `code === 404` to both predicates and a regression test for `isK8s404`.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-04-25 21:53:59 +00:00
committed by Hugh Commit [agent]
parent 719c8b7030
commit 3daf2dd676
4 changed files with 32 additions and 1 deletions
+27
View File
@@ -1185,3 +1185,30 @@ describe("ensureAgentDbPvc — unit", () => {
expect(vi.mocked(getPvc)).toHaveBeenCalledWith(NAMESPACE, `opencode-db-${expectedSlug}`, undefined);
});
});
describe("isK8s404", () => {
it("recognizes @kubernetes/client-node v1.x ApiException with code=404", async () => {
const { isK8s404 } = await import("./execute.js");
const err = Object.assign(new Error("not found"), { code: 404 });
expect(isK8s404(err)).toBe(true);
});
it("still recognizes legacy errors with statusCode=404", async () => {
const { isK8s404 } = await import("./execute.js");
const err = Object.assign(new Error("not found"), { statusCode: 404 });
expect(isK8s404(err)).toBe(true);
});
it("still recognizes errors with response.statusCode=404", async () => {
const { isK8s404 } = await import("./execute.js");
const err = Object.assign(new Error("not found"), { response: { statusCode: 404 } });
expect(isK8s404(err)).toBe(true);
});
it("returns false for non-404 errors", async () => {
const { isK8s404 } = await import("./execute.js");
expect(isK8s404(Object.assign(new Error("server error"), { code: 500 }))).toBe(false);
expect(isK8s404(new Error("plain error"))).toBe(false);
expect(isK8s404(null)).toBe(false);
});
});