{"record":{"id":"4f8430f288fea8ef","repo":"can1357/oh-my-pi","slug":"cannot-delete-an-invalid-openai-file-handle","errorCode":null,"errorMessage":"Cannot delete an invalid OpenAI file handle","messagePattern":"Cannot delete an invalid OpenAI file handle","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/provider-files-openai.ts","lineNumber":128,"sourceCode":"\t\t\tconst file = parseOpenAIFileResponse(payload);\n\t\t\tif (file.status === \"error\") throw new Error(\"OpenAI Files API reported that the upload failed\");\n\n\t\t\tconst deleteUrl = `${OPENAI_FILES_URL}/${encodeURIComponent(file.id)}`;\n\t\t\treturn {\n\t\t\t\tprovider: \"openai\",\n\t\t\t\tid: file.id,\n\t\t\t\tmimeType: uploadRequest.mimeType,\n\t\t\t\tbytes: file.bytes,\n\t\t\t\tdelete: {\n\t\t\t\t\tmethod: \"DELETE\",\n\t\t\t\t\turl: deleteUrl,\n\t\t\t\t\theaders: { Authorization: authorization },\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tasync delete(handle: ProviderFileHandle): Promise<void> {\n\t\t\tif (handle.provider !== \"openai\" || typeof handle.id !== \"string\" || handle.id.trim().length === 0) {\n\t\t\t\tthrow new Error(\"Cannot delete an invalid OpenAI file handle\");\n\t\t\t}\n\n\t\t\tlet response: Response;\n\t\t\ttry {\n\t\t\t\tresponse = await request(`${OPENAI_FILES_URL}/${encodeURIComponent(handle.id)}`, {\n\t\t\t\t\tmethod: \"DELETE\",\n\t\t\t\t\theaders: { Authorization: authorization },\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tthrow new Error(\"OpenAI Files API delete request failed\");\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`OpenAI Files API delete failed with HTTP ${response.status}`);\n\t\t\t}\n\t\t},\n\t};\n}\n","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/provider-files-openai.ts#L110-L146","documentation":"Thrown by the client's delete() when the passed ProviderFileHandle is not an OpenAI handle or lacks a non-empty string id. The client guards its own contract: it will not issue a DELETE against a malformed handle. It is a programming error — a wrong or corrupted handle object — not an API failure.","triggerScenarios":"Calling client.delete() with a handle from a different provider (e.g. provider: \"google\"), a deserialized/JSON round-tripped handle that lost its id, or a hand-built object { provider: \"openai\" } without id, or id: \"\" / whitespace.","commonSituations":"Persisting handles to disk and restoring them into the wrong client; mixing handles across broker backends; upstream responses that omitted the id field before the handle was stored.","solutions":["Check the handle's provider field matches \"openai\" and that id is a non-empty string before calling delete()","Fix the code path that produced the handle — verify the upload succeeded (errors 750–753) and its return value was stored intact","If handles are persisted, validate their shape on load and drop/repair invalid ones instead of passing them to delete()"],"exampleFix":"// before\ncleanup(handle); // may throw \"Cannot delete an invalid OpenAI file handle\"\n// after\ntypeGuard(handle) && cleanup(handle);\nfunction typeGuard(h: ProviderFileHandle): boolean {\n  return h.provider === \"openai\" && typeof h.id === \"string\" && h.id.trim().length > 0;\n}","handlingStrategy":"type-guard","validationCode":"// validate before calling delete\nif (handle.provider !== \"openai\" || typeof handle.id !== \"string\" || !handle.id.trim()) {\n  throw new Error(\"skipping cleanup: not a valid openai handle\");\n}","typeGuard":"function isValidOpenAIHandle(h: ProviderFileHandle): h is ProviderFileHandle & { provider: \"openai\"; id: string } {\n  return h.provider === \"openai\" && typeof h.id === \"string\" && h.id.trim().length > 0;\n}","tryCatchPattern":"if (!isValidOpenAIHandle(handle)) return; // skip, don't crash cleanup\ntry {\n  await client.delete(handle);\n} catch (err) {\n  logger.warn(\"openai delete skipped/failed\", { id: handle.id, err });\n}","preventionTips":["Persist handles only after a successful upload returns them","Validate persisted handles on load; drop malformed entries early","Never mix handles across provider clients","Keep provider and id fields non-optional in your handle serialization schema"],"tags":["validation","type-guard","openai"],"backgroundTag":"invalid-handle","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}