{"record":{"id":"dcb7ef465c1dded7","repo":"OpenNHP/opennhp","slug":"failed-to-download-ztdo-v","errorCode":null,"errorMessage":"failed to download ztdo: %v","messagePattern":"failed to download ztdo: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/agent/udpagent.go","lineNumber":1374,"sourceCode":"\t\t\tdataPrkWrapping := ztdolib.DataPrivateKeyWrapping{}\n\n\t\t\tif err := json.Unmarshal([]byte(dagMsg.Kao.WrappedDataKey), &dataPrkWrapping); err != nil {\n\t\t\t\tlog.Error(\"failed to unmarshal data private key wrapping: %v\\n\", err)\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to unmarshal data private key wrapping: %v\", err)\n\t\t\t}\n\n\t\t\tproviderPbk, _ := base64.StdEncoding.DecodeString(dataPrkWrapping.ProviderPublicKeyBase64)\n\n\t\t\tif dagMsg.AccessUrl == \"\" {\n\t\t\t\tlog.Error(\"access url is empty, please check with data provider\")\n\t\t\t\treturn \"\", fmt.Errorf(\"access url is empty, please check with data provider\")\n\t\t\t}\n\n\t\t\tvar err error\n\t\t\tztdoPath, err := utils.DownloadFileToTemp(dagMsg.AccessUrl, \"ztdo-\")\n\t\t\tif err != nil {\n\t\t\t\tlog.Error(\"failed to download ztdo: %v\\n\", err)\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to download ztdo: %v\", err)\n\t\t\t}\n\n\t\t\tif parseErr := ztdo.ParseHeader(ztdoPath); parseErr != nil {\n\t\t\t\tfmt.Printf(\"Error: failed to parse ztdo header:%s\\n\", parseErr)\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to parse ztdo header:%s\", parseErr)\n\t\t\t}\n\n\t\t\tif ztdoId != ztdo.GetObjectID() {\n\t\t\t\tfmt.Printf(\"Error: ztdo id mismatch, please check with data provider\\n\")\n\t\t\t\treturn \"\", fmt.Errorf(\"ztdo id mismatch, please check with data provider\")\n\t\t\t}\n\n\t\t\t// decrypt data private key\n\t\t\tsaDataPrk := ztdolib.NewSymmetricAgreement(ztdo.GetECCMode(), false)\n\t\t\tsaDataPrk.SetMessagePatterns(ztdolib.DataPrivateKeyWrappingPatterns)\n\t\t\tsaDataPrk.SetPsk([]byte(ztdolib.InitialDHPKeyWrappingString))\n\t\t\tsaDataPrk.SetStaticKeyPair(teeEcdh)\n\t\t\tsaDataPrk.SetEphemeralKeyPair(consumerEphemeralEcdh)","sourceCodeStart":1356,"sourceCodeEnd":1392,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/agent/udpagent.go#L1356-L1392","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: opaque wrap only\nif err != nil {\n    return \"\", fmt.Errorf(\"failed to download ztdo: %v\", err)\n}\n\n// after: retry once before giving up\nvar ztdoPath string\nvar err error\nfor i := 0; i < 2; i++ {\n    ztdoPath, err = utils.DownloadFileToTemp(dagMsg.AccessUrl, \"ztdo-\")\n    if err == nil {\n        break\n    }\n    time.Sleep(2 * time.Second)\n}\nif err != nil {\n    return \"\", fmt.Errorf(\"failed to download ztdo: %v\", err)\n}","handlingStrategy":"retry","validationCode":"u, err := url.Parse(dagMsg.AccessUrl)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"malformed access url: %q\", dagMsg.AccessUrl)\n}","typeGuard":"func isDownloadable(u string) bool { p, err := url.Parse(u); return err == nil && (p.Scheme == \"https\" || p.Scheme == \"http\") && p.Host != \"\" }","tryCatchPattern":"var ztdoPath string\nvar err error\nfor attempt := 0; attempt < 3; attempt++ {\n    ztdoPath, err = utils.DownloadFileToTemp(accessUrl, \"ztdo-\")\n    if err == nil { break }\n    time.Sleep(time.Duration(attempt+1) * time.Second)\n}","preventionTips":["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."],"tags":["network","http","download","ztdo"],"backgroundTag":"http-request-failed","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}