usememos/memos · error

Internal

Internal

Error message

all instance stats subtasks failed

What it means

GetInstanceStats fans out two concurrent subtasks (host/system stats and local-storage size walk) via an errgroup, collecting per-subtask results. If BOTH fail (len(results) == totalSubtasks), the whole RPC fails with this Internal error; each individual failure is also logged as a slog.Warn. Partial success still returns a stats object.

Source

Thrown at server/router/api/v1/instance_stats.go:128

	g.Go(func() error {
		size, err := walkLocalStorage(s.Profile.Data)
		if err != nil {
			record("local_storage", err)
			return nil
		}
		stats.LocalStorageBytes = size
		return nil
	})

	_ = g.Wait()

	for _, r := range results {
		slog.Warn("instance stats subtask failed", slog.String("subtask", r.name), slog.String("err", r.err.Error()))
	}

	const totalSubtasks = 2
	if len(results) == totalSubtasks {
		return nil, errors.New("all instance stats subtasks failed")
	}
	return stats, nil
}

// walkLocalStorage returns the recursive size of dir in bytes.
// Symlinks are not followed; per-entry errors below the root are ignored
// (the walk continues). An error accessing the root itself is returned.
func walkLocalStorage(dir string) (int64, error) {
	if dir == "" {
		return -1, errors.New("empty data directory")
	}
	var total int64
	err := filepath.WalkDir(dir, func(path string, entry os.DirEntry, walkErr error) error {
		if walkErr != nil {
			if path == dir {
				// Root itself is inaccessible — abort the walk.
				return walkErr
			}

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Check the server logs for the two 'instance stats subtask failed' warn lines naming the exact subtask errors.
  2. Verify the memos data directory exists and is readable/writable by the process user (check DATA variable / --data flag).
  3. If running in Docker, confirm the volume is mounted correctly and not read-only.
  4. If only one subtask failed, stats still return; harden or fix that specific collector instead of the whole RPC.
Defensive patterns

Strategy: retry

Try / catch

try {
  stats = await getInstanceStats({});
} catch (e) {
  if (e.code === 'internal' && e.message.includes('all instance stats subtasks failed')) {
    // transient fs/host issues can clear; retry once after a short delay, then surface
    stats = await retryOnce(getInstanceStats, {});
  } else throw e;
}

Prevention

When it happens

Trigger: Host stats collection errors (os.Hostname, boot time, or sysinfo failure) AND the local data directory walk fails (e.g. empty/unusable data dir, permission denied at the root) in the same call.

Common situations: The instance data directory was moved, unmounted, or made unreadable by the running user; container with an inaccessible volume mount; exotic host where sysinfo cannot read kernel stats; disk full or fs errors during the recursive walk.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/4a348f7dea341c0e. Report an issue: GitHub.