OpenNHP/opennhp · error
ztdo path or output is empty
Error message
ztdo path or output is empty
What it means
Internal invariant check after unwrapping the data private key: the downloaded ztdo temp path or the caller-supplied output path is empty. In practice ztdoPath is set by successful download, so this almost always means the output argument was passed as an empty string by the calling CLI/HTTP handler.
Solutions
- Pass a non-empty output path/argument when requesting the ztdo (CLI: --output <path>).
- Check the calling code path that builds the output value for an empty-default bug.
- Add earlier validation of the output argument before initiating the network flow.
Example fix
// before: validated only deep in the flow
if ztdoPath == "" || output == "" {
return "", fmt.Errorf("ztdo path or output is empty")
}
// after: validate at entry
func (a *UdpAgent) GetZtdoData(ztdoId, output string, ...) (string, error) {
if output == "" {
return "", fmt.Errorf("--output is required")
}
...
} Defensive patterns
Strategy: validation
Validate before calling
if ztdoId == "" || output == "" {
return fmt.Errorf("both ztdo-id and output must be provided")
} Type guard
func argsValid(ztdoId, output string) bool { return strings.TrimSpace(ztdoId) != "" && strings.TrimSpace(output) != "" } Try / catch
out, err := agent.GetZtdoData(ztdoId, output)
var merr *MissingArgError
if errors.As(err, &merr) {
// prompt user for --output instead of failing silently
} Prevention
- Require --output in CLI flag validation (cli.StringFlag Required: true).
- Validate arguments at function entry, not deep in the download path.
- In wrappers, `set -u`/explicit checks so unset variables don't yield empty strings.
When it happens
Trigger: GetZtdoData is invoked with output == "" — e.g. the CLI --output flag or HTTP request parameter was omitted, or an earlier branch overwrote output with an empty default.
Common situations: User runs the decrypt command without --output; a wrapper script drops the output variable; CLI defaults were changed so the flag no longer has a value.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- AuthServiceId is required
- invalid --data-source-type, allowed values are online…
- --source, --output, --data-source-type and --metadata are…
- --source is required when --data-source-type is not stream…
- --access-url is required when --data-source-type is stream
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/dc4d4deb028e41e1.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/agent/udpagent.go:1403
}
// 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)
saDataPrk.SetRemoteStaticPublicKey(providerPbk)
gcmKey, ad := saDataPrk.AgreeSymmetricKey()
dataPrkBase64, err := dataPrkWrapping.Unwrap(gcmKey[:], ad)
if err != nil {
return "", fmt.Errorf("failed to unwrap data private key: %s", err)
}
if ztdoPath == "" || output == "" {
return "", fmt.Errorf("ztdo path or output is empty")
}
// decrypt data
dataKeyPairEccMode := ztdo.GetECCMode()
dataMsgPattern := [][]ztdolib.MessagePattern{
{ztdolib.MessagePatternS, ztdolib.MessagePatternDHSS},
{ztdolib.MessagePatternRS, ztdolib.MessagePatternDHSS},
}
dataPrk, _ := base64.StdEncoding.DecodeString(dataPrkBase64)
saData := ztdolib.NewSymmetricAgreement(dataKeyPairEccMode, false)
saData.SetMessagePatterns(dataMsgPattern)
saData.SetStaticKeyPair(core.ECDHFromKey(dataKeyPairEccMode.ToEccType(), dataPrk))
providerPublicKey, _ := base64.StdEncoding.DecodeString(dataPrkWrapping.ProviderPublicKeyBase64)
saData.SetRemoteStaticPublicKey(providerPublicKey)
View on GitHub (pinned to 6e04ca5ff0)