{"record":{"id":"301924ea4205e564","repo":"can1357/oh-my-pi","slug":"plik-upload-metadata-did-not-include-an-id-and-upl","errorCode":null,"errorMessage":"plik upload metadata did not include an id and upload token","messagePattern":"plik upload metadata did not include an id and upload token","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploaders-self-hosted.ts","lineNumber":73,"sourceCode":"\t\tthrow new Error(\"owncloud share response did not include OCS metadata and data\");\n\t}\n\tconst meta = ocs.meta;\n\tconst data = ocs.data;\n\tif (typeof meta !== \"object\" || meta === null || !(\"statuscode\" in meta)) {\n\t\tthrow new Error(\"owncloud share response did not include an OCS status\");\n\t}\n\tif (typeof data !== \"object\" || data === null || !(\"url\" in data)) {\n\t\tthrow new Error(\"owncloud share response did not include a URL\");\n\t}\n\tconst url = nonEmptyString(data.url);\n\tif (!url) throw new Error(\"owncloud share response did not include a URL\");\n\tconst id = \"id\" in data ? identifier(data.id) : undefined;\n\treturn { statusCode: meta.statuscode, url, ...(id ? { id } : {}) };\n}\n\nfunction plikUpload(value: unknown): PlikUpload {\n\tif (typeof value !== \"object\" || value === null || !(\"id\" in value) || !(\"uploadToken\" in value)) {\n\t\tthrow new Error(\"plik upload metadata did not include an id and upload token\");\n\t}\n\tconst id = identifier(value.id);\n\tconst uploadToken = nonEmptyString(value.uploadToken);\n\tif (!id || !uploadToken) throw new Error(\"plik upload metadata did not include an id and upload token\");\n\tlet downloadBase: string | undefined;\n\tif (\"downloadURL\" in value) downloadBase = nonEmptyString(value.downloadURL);\n\tif (!downloadBase && \"downloadDomain\" in value) downloadBase = nonEmptyString(value.downloadDomain);\n\treturn { id, uploadToken, ...(downloadBase ? { downloadBase } : {}) };\n}\n\nfunction requiredStringOption(config: DestinationRuntimeConfig, key: string): string {\n\tconst value = requireOption(config, key);\n\tif (typeof value !== \"string\" || value.trim() === \"\") {\n\t\tthrow new Error(`Destination option ${key} must be a non-empty string`);\n\t}\n\treturn value.trim();\n}\n","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploaders-self-hosted.ts#L55-L91","documentation":"Thrown by the plikUpload validator when the Plik upload server's JSON response is missing either the 'id' or 'uploadToken' field (or is not an object). Both are required to finalize a Plik upload: id identifies the upload session and uploadToken authorizes subsequent calls.","triggerScenarios":"POSTing the file to a Plik server (createPlikUploader -> metadata -> plikUpload) and receiving a JSON body without id/uploadToken — e.g. the server returned an error JSON like { message: \"invalid upload\" } with 200, or the endpoint URL is wrong so a different route answered.","commonSituations":"Misconfigured plikd URL (hitting the UI instead of the API), Plik server rejecting the request due to missing/invalid upload token header while still returning JSON, or a proxy returning a JSON error page.","solutions":["Check that the configured plik apiUrl points to the Plik API root (e.g. https://plik.example.com) not a UI route","Verify the server's response with curl (curl -F file=@x https://plik.example.com) — it should contain id and uploadToken","Check Plik server logs for rejection reasons (size limits, auth requirements, expired tokens)","Ensure any required Plik authentication options are set in the destination config"],"exampleFix":"// before: hitting the UI path returns HTML/JSON without tokens\napiUrl = \"https://plik.example.com/\" // if behind a path-mangling proxy this can route wrong\n// after: verify the API answers directly\nconst resp = await fetch(\"https://plik.example\"); const meta = await resp.json(); if (!meta.id || !meta.uploadToken) throw new Error(meta.message ?? \"plik rejected upload\");","handlingStrategy":"validation","validationCode":"const res = await fetch(plikApi, { method: \"POST\", body: form });\nconst meta = await res.json();\nif (typeof meta?.id === \"undefined\" || typeof meta?.uploadToken !== \"string\" || !meta.uploadToken) {\n  throw new Error(`plik rejected upload: ${JSON.stringify(meta).slice(0, 200)}`);\n}","typeGuard":"function isPlikUploadMeta(value: unknown): value is { id: string | number; uploadToken: string } {\n  if (typeof value !== \"object\" || value === null) return false;\n  const v = value as { id?: unknown; uploadToken?: unknown };\n  const idOk = typeof v.id === \"string\" || typeof v.id === \"number\";\n  return idOk && typeof v.uploadToken === \"string\" && v.uploadToken.length > 0;\n}","tryCatchPattern":"try {\n  const up = await uploader.upload(blob);\n} catch (err) {\n  if ((err as Error).message.includes(\"id and upload token\")) {\n    throw new Error(\"plik server response lacked id/uploadToken — check apiUrl points to the Plik API and auth options are set\");\n  }\n  throw err;\n}","preventionTips":["Verify the Plik server responds correctly with curl before wiring the destination","Point apiUrl at the plikd API root, not a UI or proxy route","Check plikd logs for size/auth rejections that produce error payloads without tokens"],"tags":["plik","upload","response-parsing","self-hosted"],"backgroundTag":"api-response-missing-field","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}