{"record":{"id":"6d584f809634e288","repo":"Budibase/budibase","slug":"invalid-signed-url","errorCode":null,"errorMessage":"Invalid signed URL","messagePattern":"Invalid signed URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/backend-core/src/objectStore/utils.ts","lineNumber":94,"sourceCode":"  if (!response.body) {\n    throw new Error(\"No response received for attachment\")\n  }\n  if (!(response.body instanceof stream.Readable)) {\n    throw new Error(\"Unexpected response body stream type\")\n  }\n  return {\n    filename: attachment.filename || fallbackFilename,\n    content: response.body,\n  }\n}\n\nexport async function processObjectStoreAttachment(\n  attachment: AutomationAttachment\n): Promise<BucketedContent> {\n  const result = objectStore.extractBucketAndPath(attachment.url)\n\n  if (result === null) {\n    throw new Error(\"Invalid signed URL\")\n  }\n\n  const { bucket, path: objectPath } = result\n  const { stream: readStream } = await objectStore.getReadStream(\n    bucket,\n    objectPath\n  )\n  const fallbackFilename = path.basename(objectPath)\n  return {\n    bucket,\n    path: objectPath,\n    filename: attachment.filename || fallbackFilename,\n    content: readStream,\n  }\n}\n\nexport async function processAutomationAttachment(\n  attachment: AutomationAttachment","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/backend-core/src/objectStore/utils.ts#L76-L112","documentation":"processObjectStoreAttachment expects attachment.url to be a signed/bucket-qualified object store URL that objectStore.extractBucketAndPath can parse into { bucket, path }. If parsing returns null — the URL is not a recognizable object store URL or signed URL — the function throws 'Invalid signed URL'.","triggerScenarios":"An automation attachment whose url is an external http(s) link, a relative path, or an object store URL from a different/unconfigured host that extractBucketAndPath cannot match — so it should be handled by processUrlAttachment instead.","commonSituations":"Automations configured with plain external file URLs but routed to the object-store processor, migrations where attachment URLs changed format (e.g. presigned URL expiry formatting or new domain), or SELF_HOSTED vs hosted URL mismatch.","solutions":["Ensure the attachment url is a genuine object store/signed URL for this installation (matches your MINIO_URL/host) so extractBucketAndPath can split it","If the URL is an external HTTP link, route it to processUrlAttachment instead of processObjectStoreAttachment","Re-generate the signed URL from the current object store configuration (expired/mis-signed URLs may fail extraction)","Check bucket/endpoint env config so URL parsing rules match the URLs actually stored"],"exampleFix":"// before\n// url: \"https://cdn.example.com/file.png\" -> processObjectStoreAttachment\n// after\n// only pass signed/object-store urls to processObjectStoreAttachment;\n// use processUrlAttachment for external http links","handlingStrategy":"validation","validationCode":"const parsed = objectStore.extractBucketAndPath(attachment.url)\nif (parsed === null) throw new Error(\"Not an object store URL\")","typeGuard":"function isStoreUrl(url: string): boolean {\n  return objectStore.extractBucketAndPath(url) !== null\n}","tryCatchPattern":"try {\n  const content = await processObjectStoreAttachment(attachment)\n} catch (err) {\n  if (err.message === \"Invalid signed URL\") {\n    // fall back to processUrlAttachment for external links\n  }\n  throw err\n}","preventionTips":["Only pass installation-signed/object-store URLs to processObjectStoreAttachment","Dispatch attachments by URL shape before processing","Keep object store host config aligned with stored URLs","Regenerate signed URLs after changing buckets/endpoints"],"tags":["object-store","url-parsing","automation","attachments"],"backgroundTag":"invalid-signed-url","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}