{"record":{"id":"1da05109c74a69b2","repo":"kopia/kopia","slug":"writing-diagnostics-output-requires-a-non-empty-di","errorCode":null,"errorMessage":"writing diagnostics output requires a non-empty directory name (specified with the '--diagnostics-output-directory' flag)","messagePattern":"writing diagnostics output requires a non-empty directory name \\(specified with the '--diagnostics-output-directory' flag\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/observability_flags.go","lineNumber":117,"sourceCode":"\tapp.Flag(\"metrics-store-on-exit\", \"Writes metrics to a file in a sub-directory of the directory specified with the --diagnostics-output-directory\").Hidden().BoolVar(&c.saveMetrics)\n\n\tc.pf.setup(app)\n\n\tapp.PreAction(c.initialize)\n}\n\nfunc (c *observabilityFlags) initialize(ctx *kingpin.ParseContext) error {\n\t// write to a separate file per command and process execution to avoid\n\t// conflicts with previously created files\n\tcommand := \"unknown\"\n\tif cmd := ctx.SelectedCommand; cmd != nil {\n\t\tcommand = strings.ReplaceAll(cmd.FullCommand(), \" \", \"-\")\n\t}\n\n\tc.outputSubdirectoryName = clock.Now().Format(\"20060102-150405-\") + command\n\n\tif (c.saveMetrics || c.pf.saveProfiles || c.pf.profileCPU) && c.outputDirectory == \"\" {\n\t\treturn errors.New(\"writing diagnostics output requires a non-empty directory name (specified with the '--diagnostics-output-directory' flag)\")\n\t}\n\n\treturn nil\n}\n\n// spanName specifies the name of the span at the start of a trace. A tracer is\n// started only when spanName is not empty.\nfunc (c *observabilityFlags) run(ctx context.Context, spanName string, f func(context.Context) error) error {\n\tif err := c.start(ctx); err != nil {\n\t\treturn errors.Wrap(err, \"unable to start observability facilities\")\n\t}\n\n\tdefer c.stop(ctx)\n\n\tif err := c.pf.start(ctx, filepath.Join(c.outputDirectory, c.outputSubdirectoryName)); err != nil {\n\t\treturn errors.Wrap(err, \"failed to start profiling\")\n\t}\n","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/cli/observability_flags.go#L99-L135","documentation":"Thrown by the observability flags initialize step when diagnostics output is requested (--save-metrics, --save-profiles, or --profile-cpu) but --diagnostics-output-directory is empty. Kopia needs a directory to write traces/profiles and refuses to guess one.","triggerScenarios":"Running any command with --save-metrics, --save-profiles, or --profile-cpu while omitting --diagnostics-output-directory (or passing an empty string for it).","commonSituations":"Enabling profiling flags in scripts/config copied from examples that included the directory flag; templated CI invocations where the directory variable is unset and expands to empty.","solutions":["Add --diagnostics-output-directory <dir> alongside the profiling flags.","Remove the --save-metrics/--save-profiles/--profile-cpu flags if diagnostics are not needed.","Ensure the script variable feeding the flag is non-empty, e.g. guard: [ -n \"$DIAG_DIR\" ] || exit 1."],"exampleFix":"// before\nkopia snapshot create --all --save-metrics\n// after\nkopia snapshot create --all --save-metrics --diagnostics-output-directory /tmp/kopia-diag","handlingStrategy":"validation","validationCode":"if wantProfiles && (diagDir == \"\") { return errors.New(\"--diagnostics-output-directory required with profiling flags\") }","typeGuard":null,"tryCatchPattern":"if out, err := cmd.CombinedOutput(); err != nil {\n  if strings.Contains(string(out), \"non-empty directory name\") { /* re-invoke with --diagnostics-output-directory set */ }\n}","preventionTips":["Always pair profiling flags with an explicit directory","Default DIAG_DIR in CI env (e.g. ${DIAG_DIR:-/tmp/kopia-diag})","Create the directory with os.MkdirAll before the run so writes succeed"],"tags":["cli","observability","profiling","missing-argument"],"backgroundTag":"missing-required-flag","analyzedSha":"82495e54b584c1ef6073c9e1be048f57f8aef078","analyzedAt":"2026-09-07T20:35:21.689Z","contentChangedAt":"2026-09-07T20:35:21.689Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}