{"record":{"id":"c96d45c7c1a63161","repo":"dbt-labs/dbt-core","slug":"post-url","errorCode":null,"errorMessage":"POST {url}","messagePattern":"POST \\{url\\}","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/dbt-ci/src/publish.rs","lineNumber":447,"sourceCode":"                if is_already_exists(status, &body) {\n                    eprintln!(\n                        \"• {filename} already published at {url}; treating as success ({status})\"\n                    );\n                    return Ok(());\n                }\n                bail!(\"upload {filename} failed: {status}\\n{body}\");\n            }\n            Err(e) if is_transient(&e) && attempt < max_attempts => {\n                let delay = backoff(attempt);\n                eprintln!(\n                    \"warning: upload attempt {attempt}/{max_attempts} for {filename} failed: {e}; retrying in {}ms\",\n                    delay.as_millis(),\n                );\n                tokio::time::sleep(delay).await;\n                continue;\n            }\n            Err(e) => {\n                return Err(anyhow::Error::new(e).context(format!(\"POST {url}\")));\n            }\n        }\n    }\n}\n\nfn build_upload_form(\n    parsed: &ParsedWheel,\n    filetype: &str,\n    metadata: &Metadata,\n    md5_digest: &str,\n    sha256_digest: &str,\n    filename: &str,\n    bytes: &Bytes,\n) -> Result<reqwest::multipart::Form> {\n    // Bytes::clone is O(1) (shared buffer), so retries don't re-copy the artifact.\n    let len = bytes.len() as u64;\n    let body: reqwest::Body = bytes.clone().into();\n    let file_part = reqwest::multipart::Part::stream_with_length(body, len)","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-ci/src/publish.rs#L429-L465","documentation":"During publish/upload_dist, the release artifact upload loop retries transient failures but when a POST ultimately fails (after retries are exhausted or a non-retryable error occurs), the reqwest error is wrapped with the context \"POST {url}\". It identifies which upload endpoint (CodeArtifact or PyPI) rejected the request.","triggerScenarios":"upload_dist, called from upload_codeartifact or upload_pypi, issues a POST that returns Err from the HTTP client — DNS failure, connection reset, TLS error, or auth endpoint rejection.","commonSituations":"Publishing a release from CI with no network access, wrong registry URL, expired CodeArtifact auth token, or PyPI outage.","solutions":["Check network/VPN connectivity to the upload URL from the CI runner.","Verify the registry URL and credentials (CodeArtifact token, PyPI API token) are current.","Re-run the publish job; transient network errors may succeed on retry.","Inspect the inner anyhow error chain for the underlying reqwest cause."],"exampleFix":"// before\nupload_pypi(url_with_expired_token, dist).await?\n// after\nlet fresh_token = refresh_codeartifact_token().await?;\nupload_pypi(url_with_fresh_token, dist).await?","handlingStrategy":"retry","validationCode":"// preflight check before publishing\ncurl -sS -o /dev/null -w '%{http_code}' \"$UPLOAD_URL\" || echo 'unreachable'","typeGuard":null,"tryCatchPattern":"match upload_dist(...).await {\n    Err(e) if e.to_string().contains(\"POST\") => {\n        // inspect root cause chain, refresh credentials, retry publish\n    }\n    other => other?,\n}","preventionTips":["Refresh CodeArtifact/PyPI tokens before each publish run.","Run a connectivity preflight in CI before the upload step.","Keep retry limits and backoff configured for transient network faults."],"tags":["network","http-post","publish","retry"],"backgroundTag":"http-request-failed","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}