{"record":{"id":"9e340d2a3e4aeeb2","repo":"denoland/deno","slug":"no-certificate-chain-returned","errorCode":null,"errorMessage":"No certificate chain returned","messagePattern":"No certificate chain returned","errorType":"exception","errorClass":"AnyError","httpStatus":null,"severity":"error","filePath":"cli/tools/publish/provenance.rs","lineNumber":531,"sourceCode":"          content: public_key,\n        },\n        proof_of_possession: BASE64_STANDARD.encode(challenge.as_ref()),\n      },\n    };\n\n    let response = self\n      .http_client\n      .post_json(url.parse()?, &request_body)?\n      .send()\n      .await?;\n\n    let body: SigningCertificateResponse =\n      http_util::body_to_json(response).await?;\n\n    let key = body\n      .signed_certificate_embedded_sct\n      .or(body.signed_certificate_detached_sct)\n      .ok_or_else(|| anyhow::anyhow!(\"No certificate chain returned\"))?;\n    Ok(key.chain.certificates)\n  }\n\n  async fn gha_request_token(&self, aud: &str) -> Result<String, AnyError> {\n    let Ok(req_url) = env::var(\"ACTIONS_ID_TOKEN_REQUEST_URL\") else {\n      bail!(\"Not running in GitHub Actions\");\n    };\n\n    let Some(token) = gha_oidc_token() else {\n      bail!(\"No OIDC token available\");\n    };\n\n    let mut url = req_url.parse::<Url>()?;\n    url.query_pairs_mut().append_pair(\"audience\", aud);\n    let res_bytes = self\n      .http_client\n      .get(url)?\n      .header(","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/cli/tools/publish/provenance.rs#L513-L549","documentation":"To sign provenance, Deno requests a short-lived certificate from Fulcio; the response must contain either `signedCertificateEmbeddedSct` or `signedCertificateDetachedSct`. When the JSON body parses but both fields are missing, there is no certificate chain to build the attestation with, and this error aborts the publish. It indicates an unexpected/empty payload from the CA endpoint rather than misuse on your side.","triggerScenarios":"`deno publish --provenance` where Fulcio responds with a structurally valid but empty signing response (outage or API change); a proxy/GHE mirror returning an error page that deserialized into default-empty fields; transient infrastructure hiccup during the signing leg.","commonSituations":"One-off CI publish failures that pass on retry; Sigstore/Fulcio incidents; environments with TLS-intercepting proxies altering responses. Local misconfiguration cannot cause this — only the network path and upstream.","solutions":["Re-run `deno publish` — the certificate request is per-run and transient upstream issues resolve themselves; the failed publish left no partial state on jsr.io.","Check Sigstore status (status.sigstore.dev) for active Fulcio incidents before retrying in a loop.","Bypass TLS-intercepting corporate proxies for api.sigstore.dev / fulcio.sigstore.dev, which can corrupt JSON bodies.","If reproducible, drop `--provenance` to unblock the release and investigate separately."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for (let attempt = 1; attempt <= 3; attempt++) {\n  try {\n    await runDeno(['publish', '--provenance']);\n    break;\n  } catch (e) {\n    if (String(e.message).includes('No certificate chain returned') && attempt < 3) {\n      await delay(15_000);\n      continue; // Fulcio hiccup; new signing attempt on the next run\n    }\n    throw e;\n  }\n}","preventionTips":["Retry provenance publishes on signing-service errors; they are per-run and transient.","Check status.sigstore.dev before forcing retries in a tight loop.","Avoid TLS-inspecting proxies on the Sigstore endpoints.","If release urgency demands, fall back to publishing without --provenance temporarily."],"tags":["publish","provenance","sigstore","fulcio","code-signing","network"],"backgroundTag":"signing-service-error","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}