{"record":{"id":"dc4d4deb028e41e1","repo":"OpenNHP/opennhp","slug":"ztdo-path-or-output-is-empty","errorCode":null,"errorMessage":"ztdo path or output is empty","messagePattern":"ztdo path or output is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/agent/udpagent.go","lineNumber":1403,"sourceCode":"\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)\n\t\t\tsaDataPrk.SetRemoteStaticPublicKey(providerPbk)\n\n\t\t\tgcmKey, ad := saDataPrk.AgreeSymmetricKey()\n\n\t\t\tdataPrkBase64, err := dataPrkWrapping.Unwrap(gcmKey[:], ad)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to unwrap data private key: %s\", err)\n\t\t\t}\n\n\t\t\tif ztdoPath == \"\" || output == \"\" {\n\t\t\t\treturn \"\", fmt.Errorf(\"ztdo path or output is empty\")\n\t\t\t}\n\n\t\t\t// decrypt data\n\t\t\tdataKeyPairEccMode := ztdo.GetECCMode()\n\n\t\t\tdataMsgPattern := [][]ztdolib.MessagePattern{\n\t\t\t\t{ztdolib.MessagePatternS, ztdolib.MessagePatternDHSS},\n\t\t\t\t{ztdolib.MessagePatternRS, ztdolib.MessagePatternDHSS},\n\t\t\t}\n\n\t\t\tdataPrk, _ := base64.StdEncoding.DecodeString(dataPrkBase64)\n\t\t\tsaData := ztdolib.NewSymmetricAgreement(dataKeyPairEccMode, false)\n\t\t\tsaData.SetMessagePatterns(dataMsgPattern)\n\t\t\tsaData.SetStaticKeyPair(core.ECDHFromKey(dataKeyPairEccMode.ToEccType(), dataPrk))\n\n\t\t\tproviderPublicKey, _ := base64.StdEncoding.DecodeString(dataPrkWrapping.ProviderPublicKeyBase64)\n\t\t\tsaData.SetRemoteStaticPublicKey(providerPublicKey)\n","sourceCodeStart":1385,"sourceCodeEnd":1421,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/agent/udpagent.go#L1385-L1421","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: validated only deep in the flow\nif ztdoPath == \"\" || output == \"\" {\n    return \"\", fmt.Errorf(\"ztdo path or output is empty\")\n}\n\n// after: validate at entry\nfunc (a *UdpAgent) GetZtdoData(ztdoId, output string, ...) (string, error) {\n    if output == \"\" {\n        return \"\", fmt.Errorf(\"--output is required\")\n    }\n    ...\n}","handlingStrategy":"validation","validationCode":"if ztdoId == \"\" || output == \"\" {\n    return fmt.Errorf(\"both ztdo-id and output must be provided\")\n}","typeGuard":"func argsValid(ztdoId, output string) bool { return strings.TrimSpace(ztdoId) != \"\" && strings.TrimSpace(output) != \"\" }","tryCatchPattern":"out, err := agent.GetZtdoData(ztdoId, output)\nvar merr *MissingArgError\nif errors.As(err, &merr) {\n    // prompt user for --output instead of failing silently\n}","preventionTips":["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."],"tags":["cli","validation","arguments","dhp"],"backgroundTag":"missing-required-argument","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"}