{"record":{"id":"c094e62e1c8fdeaa","repo":"multica-ai/multica","slug":"attachment-has-no-download-url","errorCode":null,"errorMessage":"attachment has no download URL","messagePattern":"attachment has no download URL","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_attachment.go","lineNumber":146,"sourceCode":"\nfunc runAttachmentDownload(cmd *cobra.Command, args []string) error {\n\tclient, err := newAPIClient(cmd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), cli.AtLeastAPITimeout(60*time.Second))\n\tdefer cancel()\n\n\t// Fetch attachment metadata (includes signed download_url).\n\tvar att map[string]any\n\tif err := client.GetJSON(ctx, \"/api/attachments/\"+args[0], &att); err != nil {\n\t\treturn fmt.Errorf(\"get attachment: %w\", err)\n\t}\n\n\tdownloadURL := strVal(att, \"download_url\")\n\tif downloadURL == \"\" {\n\t\treturn fmt.Errorf(\"attachment has no download URL\")\n\t}\n\n\tfilename := filepath.Base(strVal(att, \"filename\"))\n\tif filename == \"\" || filename == \".\" {\n\t\tfilename = args[0]\n\t}\n\n\t// Download the file content.\n\tdata, err := client.DownloadFile(ctx, downloadURL)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"download file: %w\", err)\n\t}\n\n\t// Write to the output directory, creating it if needed so `-o` works\n\t// against a directory that does not exist yet (the help example's\n\t// `-o ./attachments` in a clean workdir).\n\toutputDir, _ := cmd.Flags().GetString(\"output-dir\")\n\tif outputDir != \"\" {","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_attachment.go#L128-L164","documentation":"After fetching attachment metadata, the command expects a non-empty download_url field (a signed URL). If the server returns metadata without a download_url, the command cannot proceed and aborts rather than guessing a URL.","triggerScenarios":"Server version that does not include signed download URLs in the metadata payload; attachment stored on object storage whose signing failed server-side; the authenticated principal is not allowed to download this attachment and the server omits the field; malformed/proxy-mangled JSON.","commonSituations":"CLI newer than a self-hosted server (field added in a later release); S3/GCS signing misconfiguration server-side; token scopes that permit metadata reads but not downloads.","solutions":["Update the self-hosted server to a version that returns download_url for attachments","Verify your token has download scope for that attachment (try from the web UI with the same account)","Inspect the raw response to confirm the field is absent: `multica attachment show <id>` or curl the metadata endpoint","Report to the server operator if signing is misconfigured"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# confirm the field exists before attempting download\ncurl -fsSH \"Authorization: Bearer $MULTICA_TOKEN\" \"$SERVER/api/attachments/$id\" | jq -e '.download_url' >/dev/null","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep CLI and server versions in lockstep so metadata always includes download_url","When automating, fetch metadata as JSON and branch on download_url presence"],"tags":["cli","attachment","api","download","version-mismatch"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}