dbt-labs/dbt-core · error · anyhow::Error

POST {url}

Error message

POST {url}

What it means

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.

Source

Thrown at crates/dbt-ci/src/publish.rs:447

                if is_already_exists(status, &body) {
                    eprintln!(
                        "• {filename} already published at {url}; treating as success ({status})"
                    );
                    return Ok(());
                }
                bail!("upload {filename} failed: {status}\n{body}");
            }
            Err(e) if is_transient(&e) && attempt < max_attempts => {
                let delay = backoff(attempt);
                eprintln!(
                    "warning: upload attempt {attempt}/{max_attempts} for {filename} failed: {e}; retrying in {}ms",
                    delay.as_millis(),
                );
                tokio::time::sleep(delay).await;
                continue;
            }
            Err(e) => {
                return Err(anyhow::Error::new(e).context(format!("POST {url}")));
            }
        }
    }
}

fn build_upload_form(
    parsed: &ParsedWheel,
    filetype: &str,
    metadata: &Metadata,
    md5_digest: &str,
    sha256_digest: &str,
    filename: &str,
    bytes: &Bytes,
) -> Result<reqwest::multipart::Form> {
    // Bytes::clone is O(1) (shared buffer), so retries don't re-copy the artifact.
    let len = bytes.len() as u64;
    let body: reqwest::Body = bytes.clone().into();
    let file_part = reqwest::multipart::Part::stream_with_length(body, len)

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Check network/VPN connectivity to the upload URL from the CI runner.
  2. Verify the registry URL and credentials (CodeArtifact token, PyPI API token) are current.
  3. Re-run the publish job; transient network errors may succeed on retry.
  4. Inspect the inner anyhow error chain for the underlying reqwest cause.

Example fix

// before
upload_pypi(url_with_expired_token, dist).await?
// after
let fresh_token = refresh_codeartifact_token().await?;
upload_pypi(url_with_fresh_token, dist).await?
Defensive patterns

Strategy: retry

Validate before calling

// preflight check before publishing
curl -sS -o /dev/null -w '%{http_code}' "$UPLOAD_URL" || echo 'unreachable'

Try / catch

match upload_dist(...).await {
    Err(e) if e.to_string().contains("POST") => {
        // inspect root cause chain, refresh credentials, retry publish
    }
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: Publishing a release from CI with no network access, wrong registry URL, expired CodeArtifact auth token, or PyPI outage.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/c96d45c7c1a63161. Report an issue: GitHub.