{"record":{"id":"f69def951bb9cc38","repo":"multica-ai/multica","slug":"download-file-w","errorCode":null,"errorMessage":"download file: %w","messagePattern":"download file: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_attachment.go","lineNumber":157,"sourceCode":"\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 != \"\" {\n\t\tif err := os.MkdirAll(outputDir, 0o755); err != nil {\n\t\t\treturn fmt.Errorf(\"create output directory: %w\", err)\n\t\t}\n\t}\n\tdestPath := filepath.Join(outputDir, filename)\n\n\tif err := os.WriteFile(destPath, data, 0o644); err != nil {\n\t\treturn fmt.Errorf(\"write file: %w\", err)\n\t}\n\n\t// Print the absolute path so agents can reference the file.","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_attachment.go#L139-L175","documentation":"Once the command has the signed download_url, it fetches the bytes with client.DownloadFile under a 60s timeout. This error wraps any failure of that fetch: expired signed URL, DNS/network failure to the storage host, or a 403 from object storage.","triggerScenarios":"Metadata was fetched but the signed URL expired before the download started (long queue, paused terminal); egress blocked to the storage domain (air-gapped agent sandbox, firewall); clock skew invalidating the signature; storage outage.","commonSituations":"Agent containers with restricted egress allowing only the API host; slow links where the 60s timeout is exceeded for large files; sitting on the metadata too long before downloading.","solutions":["Retry the download — a fresh run gets a newly signed URL","Allow egress to the storage/host serving download_url in firewall/proxy rules","For large files on slow links, download from a machine with better bandwidth or increase the CLI timeout env if supported","Check system clock (significant skew can invalidate signatures)"],"exampleFix":"# retry pattern in shell (fresh signed URL each attempt)\nfor i in 1 2 3; do multica attachment download \"$id\" -o ./attachments && break; sleep 5; done","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"# signed URLs are freshly minted per run — one retry fixes expiry\nfor i in 1 2; do multica attachment download \"$id\" -o ./attachments && exit 0; sleep 2; done; exit 1","preventionTips":["Download immediately after fetching metadata — signed URLs have short lifetimes","Allow egress to the storage host in firewall rules for agent environments"],"tags":["cli","attachment","network","download","signed-url"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}