{"record":{"id":"181725f9e5ecb1a4","repo":"OpenNHP/opennhp","slug":"error-fail-to-request-ztdo-with-error-s","errorCode":null,"errorMessage":"Error: fail to request ztdo with error: %s.","messagePattern":"Error: fail to request ztdo with error: (.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/agent/udpagent.go","lineNumber":1438,"sourceCode":"\t\t\tsaData.SetRemoteStaticPublicKey(providerPublicKey)\n\n\t\t\tgcmKey, ad = saData.AgreeSymmetricKey()\n\n\t\t\tif err := ztdo.DecryptZtdoFile(ztdoPath, output, gcmKey[:], ad); err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"Failed to decrypt ztdo file: %v\", err)\n\t\t\t} else {\n\t\t\t\ta.decryptedZtdoRecord[ztdoId] = output\n\t\t\t}\n\t\t} else {\n\t\t\toutput = decryptedOutput\n\t\t}\n\t} else {\n\t\tteeNotAuthorizedCode, _ := strconv.Atoi(common.ErrTEENotAuthorized.ErrorCode())\n\t\tif dagMsg.ErrCode == teeNotAuthorizedCode {\n\t\t\ta.trustedByNHPDB.Store(false)\n\t\t}\n\n\t\treturn \"\", fmt.Errorf(\"Error: fail to request ztdo with error: %s.\", dagMsg.ErrMsg)\n\t}\n\treturn output, nil\n}\n\n// GetFirstServerPeer returns the representative peer of an arbitrary\n// configured cluster. Used by legacy resource-agnostic paths\n// (registration, DHP) that don't have a KnockResource to route by.\n//\n// Semantics caveat: when multiple clusters are configured, map\n// iteration order is intentionally unspecified — the result is \"any\n// configured cluster\". Multi-cluster deployments that exercise these\n// paths must either route via a KnockResource (so pubkey selection\n// applies) or accept that registration/DHP land on whichever cluster\n// happens to win the iteration. The caller logs at WARNING level when\n// multiple clusters exist so this behavior is at least visible.\nfunc (a *UdpAgent) GetFirstServerPeer() (serverPeer *core.UdpPeer) {\n\ta.serverPeerMutex.Lock()\n\tdefer a.serverPeerMutex.Unlock()","sourceCodeStart":1420,"sourceCodeEnd":1456,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/agent/udpagent.go#L1420-L1456","documentation":"The NHP-DB responded to the ztdo request with a non-zero error code; the agent surfaces dagMsg.ErrMsg verbatim. If the specific error is TEE-not-authorized, the agent additionally marks itself as not trusted by the NHP-DB (trustedByNHPDB.Store(false)). The real cause is always inside dagMsg.ErrMsg.","triggerScenarios":"dagMsg.ErrCode != 0 in the DB's reply — e.g. unknown ztdo id, unauthorized agent, TEE attestation not accepted, provider unreachable from the DB, or internal DB failure.","commonSituations":"Agent not registered/trusted by the NHP-DB (TEE not authorized); typo'd ztdo-id; provider service down so DB can't fetch the access URL; DB auth policy rejecting the agent's identity after key rotation.","solutions":["Read dagMsg.ErrMsg in the error text — it names the actual DB-side cause.","If 'TEE not authorized': re-register the agent/TEE with the NHP-DB and restore trust (trustedByNHPDB).","Verify the ztdo-id exists at the provider and the provider service is online.","Check agent keys/registration against the DB's agent.toml after any key rotation.","Inspect NHP-DB server logs for the request to get the full internal error."],"exampleFix":"// before: trust flag never re-checked\nif dagMsg.ErrCode == teeNotAuthorizedCode {\n    a.trustedByNHPDB.Store(false)\n}\n\n// after: also gate and re-register before next attempt\nif dagMsg.ErrCode == teeNotAuthorizedCode {\n    a.trustedByNHPDB.Store(false)\n    if err := a.RegisterWithNHPDB(); err != nil {\n        return \"\", fmt.Errorf(\"re-registration failed after tee-not-authorized: %w\", err)\n    }\n}","handlingStrategy":"try-catch","validationCode":"if dagMsg.ErrCode != 0 {\n    log.Printf(\"ztdo request rejected by NHP-DB: code=%d msg=%s\", dagMsg.ErrCode, dagMsg.ErrMsg)\n}","typeGuard":"func isTeeNotAuthorized(dagMsg *common.DataAckMsg) bool {\n    code, _ := strconv.Atoi(common.ErrTEENotAuthorized.ErrorCode())\n    return dagMsg != nil && dagMsg.ErrCode == code\n}","tryCatchPattern":"path, err := agent.GetZtdoData(ztdoId, output)\nif err != nil && strings.Contains(err.Error(), \"not authorized\") {\n    // re-register agent/TEE with NHP-DB, then retry once\n}","preventionTips":["Keep agent registration and TEE attestation current with the NHP-DB.","Re-run registration after any key rotation on either side.","Log ErrCode/ErrMsg pairs centrally to map codes to root causes."],"tags":["network","nhp-db","authorization","ztdo"],"backgroundTag":"api-error-response","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"}