OpenNHP/opennhp · error
Error: fail to request ztdo with error
Error message
Error: fail to request ztdo with error: %s.
What it means
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.
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.
Example fix
// before: trust flag never re-checked
if dagMsg.ErrCode == teeNotAuthorizedCode {
a.trustedByNHPDB.Store(false)
}
// after: also gate and re-register before next attempt
if dagMsg.ErrCode == teeNotAuthorizedCode {
a.trustedByNHPDB.Store(false)
if err := a.RegisterWithNHPDB(); err != nil {
return "", fmt.Errorf("re-registration failed after tee-not-authorized: %w", err)
}
} Defensive patterns
Strategy: try-catch
Validate before calling
if dagMsg.ErrCode != 0 {
log.Printf("ztdo request rejected by NHP-DB: code=%d msg=%s", dagMsg.ErrCode, dagMsg.ErrMsg)
} Type guard
func isTeeNotAuthorized(dagMsg *common.DataAckMsg) bool {
code, _ := strconv.Atoi(common.ErrTEENotAuthorized.ErrorCode())
return dagMsg != nil && dagMsg.ErrCode == code
} Try / catch
path, err := agent.GetZtdoData(ztdoId, output)
if err != nil && strings.Contains(err.Error(), "not authorized") {
// re-register agent/TEE with NHP-DB, then retry once
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- access url is empty, please check with data provider
- failed to download ztdo
- failed to parse default route
- Failed to refresh SDP
- fail to call trusted application with error
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/181725f9e5ecb1a4.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/agent/udpagent.go:1438
saData.SetRemoteStaticPublicKey(providerPublicKey)
gcmKey, ad = saData.AgreeSymmetricKey()
if err := ztdo.DecryptZtdoFile(ztdoPath, output, gcmKey[:], ad); err != nil {
return "", fmt.Errorf("Failed to decrypt ztdo file: %v", err)
} else {
a.decryptedZtdoRecord[ztdoId] = output
}
} else {
output = decryptedOutput
}
} else {
teeNotAuthorizedCode, _ := strconv.Atoi(common.ErrTEENotAuthorized.ErrorCode())
if dagMsg.ErrCode == teeNotAuthorizedCode {
a.trustedByNHPDB.Store(false)
}
return "", fmt.Errorf("Error: fail to request ztdo with error: %s.", dagMsg.ErrMsg)
}
return output, nil
}
// GetFirstServerPeer returns the representative peer of an arbitrary
// configured cluster. Used by legacy resource-agnostic paths
// (registration, DHP) that don't have a KnockResource to route by.
//
// Semantics caveat: when multiple clusters are configured, map
// iteration order is intentionally unspecified — the result is "any
// configured cluster". Multi-cluster deployments that exercise these
// paths must either route via a KnockResource (so pubkey selection
// applies) or accept that registration/DHP land on whichever cluster
// happens to win the iteration. The caller logs at WARNING level when
// multiple clusters exist so this behavior is at least visible.
func (a *UdpAgent) GetFirstServerPeer() (serverPeer *core.UdpPeer) {
a.serverPeerMutex.Lock()
defer a.serverPeerMutex.Unlock()View on GitHub (pinned to 6e04ca5ff0)