OpenNHP/opennhp · error
failed to download ztdo
Error message
failed to download ztdo: %v
What it means
The agent failed to download the ztdo file from dagMsg.AccessUrl via utils.DownloadFileToTemp. The underlying error (DNS failure, HTTP error status, TLS problem, disk write failure) is wrapped verbatim. This is a network/IO error on the client side while fetching the provider-hosted payload.
Solutions
- Inspect the wrapped inner error to identify whether it is DNS, HTTP status, TLS, or disk IO.
- Test the AccessUrl directly with curl from the agent host to reproduce.
- Re-request the ztdo to get a fresh (non-expired) URL from the provider.
- Ensure the provider's storage endpoint is publicly reachable or on a network path reachable by the agent.
- Check local temp directory permissions and free disk space.
Example fix
// before: opaque wrap only
if err != nil {
return "", fmt.Errorf("failed to download ztdo: %v", err)
}
// after: retry once before giving up
var ztdoPath string
var err error
for i := 0; i < 2; i++ {
ztdoPath, err = utils.DownloadFileToTemp(dagMsg.AccessUrl, "ztdo-")
if err == nil {
break
}
time.Sleep(2 * time.Second)
}
if err != nil {
return "", fmt.Errorf("failed to download ztdo: %v", err)
} Defensive patterns
Strategy: retry
Validate before calling
u, err := url.Parse(dagMsg.AccessUrl)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("malformed access url: %q", dagMsg.AccessUrl)
} Type guard
func isDownloadable(u string) bool { p, err := url.Parse(u); return err == nil && (p.Scheme == "https" || p.Scheme == "http") && p.Host != "" } Try / catch
var ztdoPath string
var err error
for attempt := 0; attempt < 3; attempt++ {
ztdoPath, err = utils.DownloadFileToTemp(accessUrl, "ztdo-")
if err == nil { break }
time.Sleep(time.Duration(attempt+1) * time.Second)
} Prevention
- Monitor pre-signed URL expiry; re-request URLs near expiry.
- curl-test provider storage endpoints from agent subnets during deploys.
- Set disk-space and temp-dir permission monitoring on agent hosts.
When it happens
Trigger: utils.DownloadFileToTemp(dagMsg.AccessUrl, "ztdo-") returns a non-nil error: unreachable host, 404/403 from object storage, expired pre-signed URL, TLS cert issues, or local temp-dir write failure.
Common situations: Expired or rotated pre-signed S3 URLs; data provider host behind firewall not reachable from the agent network; DNS misconfiguration; provider URL points to localhost/internal address; disk full on the agent host.
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
- access url is empty, please check with data provider
- Error: fail to request ztdo with error
- could not send https request
- could not read response body
- failed to download HRK
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/dcb7ef465c1dded7.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/agent/udpagent.go:1374
dataPrkWrapping := ztdolib.DataPrivateKeyWrapping{}
if err := json.Unmarshal([]byte(dagMsg.Kao.WrappedDataKey), &dataPrkWrapping); err != nil {
log.Error("failed to unmarshal data private key wrapping: %v\n", err)
return "", fmt.Errorf("failed to unmarshal data private key wrapping: %v", err)
}
providerPbk, _ := base64.StdEncoding.DecodeString(dataPrkWrapping.ProviderPublicKeyBase64)
if dagMsg.AccessUrl == "" {
log.Error("access url is empty, please check with data provider")
return "", fmt.Errorf("access url is empty, please check with data provider")
}
var err error
ztdoPath, err := utils.DownloadFileToTemp(dagMsg.AccessUrl, "ztdo-")
if err != nil {
log.Error("failed to download ztdo: %v\n", err)
return "", fmt.Errorf("failed to download ztdo: %v", err)
}
if parseErr := ztdo.ParseHeader(ztdoPath); parseErr != nil {
fmt.Printf("Error: failed to parse ztdo header:%s\n", parseErr)
return "", fmt.Errorf("failed to parse ztdo header:%s", parseErr)
}
if ztdoId != ztdo.GetObjectID() {
fmt.Printf("Error: ztdo id mismatch, please check with data provider\n")
return "", fmt.Errorf("ztdo id mismatch, please check with data provider")
}
// decrypt data private key
saDataPrk := ztdolib.NewSymmetricAgreement(ztdo.GetECCMode(), false)
saDataPrk.SetMessagePatterns(ztdolib.DataPrivateKeyWrappingPatterns)
saDataPrk.SetPsk([]byte(ztdolib.InitialDHPKeyWrappingString))
saDataPrk.SetStaticKeyPair(teeEcdh)
saDataPrk.SetEphemeralKeyPair(consumerEphemeralEcdh)View on GitHub (pinned to 6e04ca5ff0)