charmbracelet/crush · error
failed to save Hyper provider to cache: %w
Error message
failed to save Hyper provider to cache: %w
What it means
UpdateHyper persists the resolved provider via newCache[catwalk.Provider](cachePathFor("hyper")).Store. This error wraps cache-write failures: missing/unwritable cache directory, disk full, permission denied, or an atomic rename failure (including Windows ERROR_ACCESS_DENIED).
Source
Thrown at internal/config/provider.go:142
resolveKey: func() string { return resolveHyperAPIKey(nil) },
}
var err error
provider, err = client.Get(context.Background(), "")
if err != nil {
return fmt.Errorf("failed to fetch provider from Hyper: %w", err)
}
default:
content, err := os.ReadFile(pathOrURL)
if err != nil {
return fmt.Errorf("failed to read file: %w", err)
}
if err := json.Unmarshal(content, &provider); err != nil {
return fmt.Errorf("failed to unmarshal provider data: %w", err)
}
}
if err := newCache[catwalk.Provider](cachePathFor("hyper")).Store(provider); err != nil {
return fmt.Errorf("failed to save Hyper provider to cache: %w", err)
}
slog.Info("Hyper provider updated successfully", "from", pathOrURL, "to", cachePathFor("hyper"))
return nil
}
var (
catwalkSyncer = &catwalkSync{}
hyperSyncer = &hyperSync{}
)
// Providers returns the list of providers, taking into account cached results
// and whether or not auto update is enabled.
//
// It will:
// 1. if auto update is disabled, it'll return the embedded providers at the
// time of release.
// 2. load the cached providersView on GitHub (pinned to 7944b8e522)
Solutions
- Check permissions and free space on the cache directory (`ls -ld`, `df -h`).
- Set XDG_CACHE_HOME to a writable directory.
- Remove a corrupt/partial hyper cache file and retry.
- In containers, mount a writable volume at the cache path.
Example fix
// before docker run -v /ro-cache:/root/.cache crush update-hyper // after docker run -v writable:/root/.cache crush update-hyper
Defensive patterns
Strategy: try-catch
Validate before calling
hyperCache := cachePathFor("hyper")
if err := os.MkdirAll(filepath.Dir(hyperCache), 0o755); err != nil {
return fmt.Errorf("cannot create hyper cache dir: %w", err)
}
probe, _ := os.CreateTemp(filepath.Dir(hyperCache), "writetest")
probe.Close(); os.Remove(probe.Name()) Try / catch
if err := config.UpdateHyper(src); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && (errors.Is(pe.Err, syscall.EACCES) || errors.Is(pe.Err, syscall.ENOSPC)) {
slog.Error("cannot write hyper cache", "path", pe.Path, "err", pe.Err)
}
return err
} Prevention
- Mount a writable volume at the cache path in containers.
- Set XDG_CACHE_HOME explicitly in CI and sandboxed environments.
- Clean up stale/partial hyper cache files after crashed runs.
- Avoid running concurrent UpdateHyper processes against the same cache.
When it happens
Trigger: Calling config.UpdateHyper when the cache location for "hyper" cannot be created or written: read-only HOME/XDG_CACHE_HOME, full disk, sandboxed container without writable cache, or antivirus locking the temp file on Windows.
Common situations: Read-only home directory in CI; disk quota exceeded; container running as non-root with a mounted read-only cache volume; concurrent runs racing on the same cache file.
Related errors
- failed to save providers to cache: %w
- docker MCP started but failed to persist configuration: %w
- failed to create server working directory: %v
- failed to persist docker mcp configuration: %w
- failed to update preferred large model: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/496341087b38c658.
Report an issue: GitHub.