Jguer/yay · error

failed to read vcs

Error message

failed to read vcs '%s': %w

What it means

Returned by InfoStore.Load when the VCS info JSON file at v.FilePath exists and opens successfully but fails to decode, i.e. json.Decoder.Decode returns an error. The file path and underlying JSON error are wrapped. It means the on-disk vcs.json cache is present but corrupt or not valid JSON for the OriginsByPackage structure.

Solutions

  1. Delete the vcs file at the reported path — it is a cache and will be recreated on next run.
  2. Inspect the file with `jq` or `json.tool` to confirm it is corrupt before deleting.
  3. Keep backups if the file holds meaningful state; otherwise treat it as disposable cache.

Example fix

rm ~/.cache/yay/vcs.json  # then rerun; store is rebuilt
Defensive patterns

Strategy: fallback

Validate before calling

if b, err := os.ReadFile(vcsFilePath); err == nil && !json.Valid(b) {
    // file is corrupt: remove it and let the store rebuild
    os.Remove(vcsFilePath)
}

Try / catch

if err := store.Load(); err != nil {
    // fall back to empty store after confirming corruption
    os.Remove(v.FilePath)
    return store.Load()
}

Prevention

When it happens

Trigger: `decoder.Decode(&v.OriginsByPackage)` errors on the vcs file: truncated file from a crash mid-write, empty/corrupt content, or JSON written by an incompatible older version.

Common situations: System crash or power loss during a previous run, disk-full truncating the file, manually edited vcs file with invalid JSON.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Jguer/yay@328f4b4939 (2026-09-07). Data as JSON: /api/errors/069bdef04c313291. Report an issue: GitHub.

Appendix: source

Thrown at pkg/vcs/vcs.go:315

		if err := v.Save(); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
	}
}

// LoadStore reads a json file and populates a InfoStore structure.
func (v *InfoStore) Load() error {
	vfile, err := os.Open(v.FilePath)
	if !os.IsNotExist(err) && err != nil {
		return fmt.Errorf("failed to open vcs file '%s': %w", v.FilePath, err)
	}

	defer vfile.Close()

	if !os.IsNotExist(err) {
		decoder := json.NewDecoder(vfile)
		if err = decoder.Decode(&v.OriginsByPackage); err != nil {
			return fmt.Errorf("failed to read vcs '%s': %w", v.FilePath, err)
		}
	}

	return nil
}

func (v *InfoStore) CleanOrphans(pkgs map[string]alpm.Package) {
	missing := make([]string, 0)

	for pkgName := range v.OriginsByPackage {
		if _, ok := pkgs[pkgName]; !ok {
			v.logger.Debugln("removing orphaned vcs package:", pkgName)
			missing = append(missing, pkgName)
		}
	}

	v.RemovePackages(missing)
}

View on GitHub (pinned to 328f4b4939)