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

  1. Pass a non-empty output path/argument when requesting the ztdo (CLI: --output <path>).
  2. Check the calling code path that builds the output value for an empty-default bug.
  3. 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

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


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)