{"record":{"id":"8770d726f9a880b1","repo":"can1357/oh-my-pi","slug":"owncloud-share-response-did-not-include-a-url","errorCode":null,"errorMessage":"owncloud share response did not include a URL","messagePattern":"owncloud share response did not include a URL","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploaders-self-hosted.ts","lineNumber":63,"sourceCode":"function identifier(value: unknown): string | undefined {\n\treturn typeof value === \"string\" || typeof value === \"number\" ? String(value) : undefined;\n}\n\nfunction ownCloudShare(value: unknown): OwnCloudShare {\n\tif (typeof value !== \"object\" || value === null || !(\"ocs\" in value)) {\n\t\tthrow new Error(\"owncloud share response did not include an OCS envelope\");\n\t}\n\tconst ocs = value.ocs;\n\tif (typeof ocs !== \"object\" || ocs === null || !(\"meta\" in ocs) || !(\"data\" in ocs)) {\n\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 } : {}) };","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploaders-self-hosted.ts#L45-L81","documentation":"Thrown when the OCS 'data' section is absent, not an object, or lacks a 'url' key. The library requires data.url because the whole point of the share call is to obtain the public share URL it hands back to the user.","triggerScenarios":"The ownCloud share endpoint returned an OCS envelope whose data object has no 'url' field — e.g. the share failed server-side (statuscode 100/403/404) so data holds an error message instead of the created share, and the caller did not check statuscode first.","commonSituations":"Insufficient permissions for the upload user to create shares, share links disabled by admin policy, sharing the target folder blocked, or requesting shares on a server where the files_sharing app is disabled.","solutions":["Check meta.statuscode in the same response: non-200 OCS status means the share was rejected — fix the underlying auth/permission problem first","Verify the upload user has share-create permission and the files_sharing app is enabled on the server","Ensure the target file/path exists (shares of nonexistent paths return no url)","Test the same share call manually with curl against the OCS API to see the server's error message in data"],"exampleFix":"// before: data contains { message: \"Could not create share\" } on failure\n// after: check OCS status before reading url, and fix server permissions\nconst parsed = ownCloudShare(body);\nif (Number(parsed.statusCode) >= 400 || Number(parsed.statusCode) === 100) throw new Error(`share rejected: ${JSON.stringify(body)}`);","handlingStrategy":"validation","validationCode":"// before trusting a share response, verify the OCS status code yourself\nconst res = await fetch(shareUrl, { headers: auth } );\nconst body = await res.json();\nconst status = Number(body?.ocs?.meta?.statuscode);\nif (status !== 200 && status !== 100) throw new Error(`share rejected by server (OCS status ${status})`);\nif (typeof body?.ocs?.data?.url !== \"string\" || !body.ocs.data.url) throw new Error(\"share response has no url — check share permissions\");","typeGuard":"function hasShareUrl(value: unknown): value is { ocs: { meta: { statuscode: unknown }; data: { url: string } } } {\n  const data = (value as any)?.ocs?.data;\n  return typeof data === \"object\" && data !== null && typeof data.url === \"string\" && data.url.length > 0;\n}","tryCatchPattern":"try {\n  const share = await uploader.share();\n} catch (err) {\n  if ((err as Error).message.includes(\"did not include a URL\")) {\n    throw new Error(\"ownCloud did not return a share URL — verify the user can create share links and files_sharing is enabled\");\n  }\n  throw err;\n}","preventionTips":["Grant the upload account share-create permissions and enable the files_sharing app","Check OCS meta.statuscode first — failures put error messages in data instead of url","Confirm the shared path exists before attempting the share"],"tags":["owncloud","nextcloud","ocs","share","permissions"],"backgroundTag":"api-response-missing-field","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}