gastownhall/beads · error

metrics: resolve data dir: %w

Error message

metrics: resolve data dir: %w

What it means

metrics.Init resolves the user's data directory (DataDir) so a file-based event emitter can be created. If DataDir fails — the data dir cannot be determined or created — Init aborts with 'metrics: resolve data dir: ...'. Telemetry cannot be set up, and the returned no-op closure is returned alongside the error so shutdown stays safe.

Source

Thrown at internal/metrics/metrics.go:67

}

func Init(version string, enable bool, metricsEndpoint string) (func(context.Context), error) {
	enabled = enable
	endpoint = metricsEndpoint
	if endpoint == "" {
		endpoint = DefaultEndpoint
	}

	var emitter eventkit.Emitter = eventkit.NullEmitter{}
	// The distinct ID is resolved only on the enabled path: computing it can
	// fork a platform probe (see cachedMachineID), and a disabled collector
	// never emits an event that would carry it. The placeholder below is inert
	// — NullEmitter drops everything and WithDisabled gates emission anyway.
	distinctID := "disabled"
	if enabled {
		dir, err := DataDir()
		if err != nil {
			return func(context.Context) {}, fmt.Errorf("metrics: resolve data dir: %w", err)
		}
		fe, err := eventkit.NewFileEmitter(dir)
		if err != nil {
			return func(context.Context) {}, fmt.Errorf("metrics: file emitter: %w", err)
		}
		emitter = fe
		distinctID = cachedMachineID(AppName)
	}

	c := eventkit.NewCollector(emitter,
		eventkit.WithDistinctID(distinctID),
		eventkit.WithAppName(AppName),
		eventkit.WithAppVersion(version),
		eventkit.WithDisabled(func() bool { return !enabled }),
	)
	eventkit.SetGlobal(c)

	return func(ctx context.Context) {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Ensure HOME (or the relevant XDG dir) is set and writable by the process.
  2. Create or fix permissions on the data directory.
  3. If telemetry is unwanted, explicitly disable metrics (enabled=false) so DataDir is never resolved.

Example fix

// before
cleanup, err := metrics.Init(ctx, true)
// after
if os.Getenv("HOME") == "" {
    cleanup, err = metrics.Init(ctx, false) // skip emitter setup
} else {
    cleanup, err = metrics.Init(ctx, true)
}
Defensive patterns

Strategy: fallback

Validate before calling

if enabled {
    if dir, err := metrics.DataDir(); err != nil {
        enabled = false // telemetry optional
    }
}

Try / catch

cleanup, err := metrics.Init(ctx, enabled)
if err != nil && strings.HasPrefix(err.Error(), "metrics: resolve data dir") {
    cleanup = func(context.Context) {}
    return nil // degrade gracefully, telemetry is non-essential
}

Prevention

When it happens

Trigger: Calling metrics.Init with enabled=true while internal/metrics.DataDir fails: unwritable $HOME/$XDG_DATA_HOME, HOME unset, or the data-dir path creation erroring.

Common situations: Containers/CI running with HOME unset or read-only; sandboxed environments blocking directory creation; disk permissions changed under the data root.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/96290260c2b56665. Report an issue: GitHub.