docker/cli · error

failed to read metadata

Error message

failed to read metadata: %w

What it means

Returned by ContextStore.List / metadataStore.list when reading one of the context directories fails with an error other than 'not exist'. Listing iterates all context dirs; not-exist errors are skipped, but any other error (parse or I/O on a single context) aborts the entire list.

Solutions

  1. Identify and remove/repair the offending context dir by checking each meta.json under ~/.docker/contexts/meta/.
  2. Fix permissions on the unreadable dir.
  3. Remove the broken context (manually if `docker context rm` also fails) and recreate it.
Defensive patterns

Strategy: try-catch

Try / catch

list, err := store.List()
if err != nil {
    // One bad context aborts listing — locate the offending dir under
    // ~/.docker/contexts/meta/*/meta.json and repair/remove it, then retry.
    return err
}

Prevention

When it happens

Trigger: Calling store.List() (e.g. `docker context ls`) when one context's meta.json is corrupt or unreadable; a single bad context poisons listing for the whole store.

Common situations: One corrupted context making `docker context ls` fail; permission denied on one context dir; partial write leaving one meta.json invalid.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/82d91e783fb66fe5. Report an issue: GitHub.

Appendix: source

Thrown at cli/context/store/metadatastore.go:121

	return nil
}

func (s *metadataStore) list() ([]Metadata, error) {
	ctxDirs, err := listRecursivelyMetadataDirs(s.root)
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {
			return nil, nil
		}
		return nil, err
	}
	res := make([]Metadata, 0, len(ctxDirs))
	for _, dir := range ctxDirs {
		c, err := s.getByID(contextdir(dir))
		if err != nil {
			if errors.Is(err, os.ErrNotExist) {
				continue
			}
			return nil, fmt.Errorf("failed to read metadata: %w", err)
		}
		res = append(res, c)
	}
	sort.Slice(res, func(i, j int) bool {
		return sortorder.NaturalLess(res[i].Name, res[j].Name)
	})
	return res, nil
}

func isContextDir(path string) bool {
	s, err := os.Stat(filepath.Join(path, metaFile))
	if err != nil {
		return false
	}
	return !s.IsDir()
}

func listRecursivelyMetadataDirs(root string) ([]string, error) {

View on GitHub (pinned to 4f84911bfe)