kopia/kopia · error
writing diagnostics output requires a non-empty directory…
Error message
writing diagnostics output requires a non-empty directory name (specified with the '--diagnostics-output-directory' flag)
What it means
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.
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.
Example fix
// before kopia snapshot create --all --save-metrics // after kopia snapshot create --all --save-metrics --diagnostics-output-directory /tmp/kopia-diag
Defensive patterns
Strategy: validation
Validate before calling
if wantProfiles && (diagDir == "") { return errors.New("--diagnostics-output-directory required with profiling flags") } Try / catch
if out, err := cmd.CombinedOutput(); err != nil {
if strings.Contains(string(out), "non-empty directory name") { /* re-invoke with --diagnostics-output-directory set */ }
} Prevention
- 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
When it happens
Trigger: Running any command with --save-metrics, --save-profiles, or --profile-cpu while omitting --diagnostics-output-directory (or passing an empty string for it).
Common situations: 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.
Understand the failure class
Background: "--flag is required" and "must specify" CLI errors: how missing-required-flag validation works and how to fix it — this error's family across 20 libraries.
Related errors
- failed to start profiling
- must specify --add and/or --remove
- must specify either --all or --sources
- must specify files to remove
- unable to start observability facilities
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/1da05109c74a69b2.
Report an issue: GitHub.
Appendix: source
Thrown at cli/observability_flags.go:117
app.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)
c.pf.setup(app)
app.PreAction(c.initialize)
}
func (c *observabilityFlags) initialize(ctx *kingpin.ParseContext) error {
// write to a separate file per command and process execution to avoid
// conflicts with previously created files
command := "unknown"
if cmd := ctx.SelectedCommand; cmd != nil {
command = strings.ReplaceAll(cmd.FullCommand(), " ", "-")
}
c.outputSubdirectoryName = clock.Now().Format("20060102-150405-") + command
if (c.saveMetrics || c.pf.saveProfiles || c.pf.profileCPU) && c.outputDirectory == "" {
return errors.New("writing diagnostics output requires a non-empty directory name (specified with the '--diagnostics-output-directory' flag)")
}
return nil
}
// spanName specifies the name of the span at the start of a trace. A tracer is
// started only when spanName is not empty.
func (c *observabilityFlags) run(ctx context.Context, spanName string, f func(context.Context) error) error {
if err := c.start(ctx); err != nil {
return errors.Wrap(err, "unable to start observability facilities")
}
defer c.stop(ctx)
if err := c.pf.start(ctx, filepath.Join(c.outputDirectory, c.outputSubdirectoryName)); err != nil {
return errors.Wrap(err, "failed to start profiling")
}
View on GitHub (pinned to 82495e54b5)