lima-vm/lima · error
caching-only mode requires the cache directory to be specifi
Error message
caching-only mode requires the cache directory to be specified
What it means
The downloader was invoked in caching-only mode (no local output path) but the Options were never given a cache directory, so there is nowhere to store or find the downloaded artifact. Download refuses to proceed rather than guessing a location.
Source
Thrown at pkg/downloader/downloader.go:199
// Download downloads the remote resource into the local path.
//
// Download caches the remote resource if WithCache or WithCacheDir option is specified.
// Local files are not cached.
//
// When the local path already exists, Download returns Result with StatusSkipped.
// (So, the local path cannot be set to /dev/null for "caching only" mode.)
//
// The local path can be an empty string for "caching only" mode.
func Download(ctx context.Context, local, remote string, opts ...Opt) (*Result, error) {
var o options
if err := o.apply(opts); err != nil {
return nil, err
}
var localPath string
if local == "" {
if o.cacheDir == "" {
return nil, errors.New("caching-only mode requires the cache directory to be specified")
}
} else {
var err error
localPath, err = canonicalLocalPath(local)
if err != nil {
return nil, err
}
if _, err := os.Stat(localPath); err == nil {
logrus.Debugf("file %#q already exists, skipping downloading from %#q (and skipping digest validation)", localPath, remote)
res := &Result{
Status: StatusSkipped,
ValidatedDigest: false,
}
return res, nil
} else if !errors.Is(err, os.ErrNotExist) {
return nil, err
}
View on GitHub (pinned to dd909d0973)
Solutions
- Set CacheDir (e.g. ~/.cache/lima) in the downloader Options before calling Download.
- Pass a non-empty local path if you actually want a direct download instead of cache-only mode.
- Review the code path that constructs the Options to ensure the cache-dir flag/env (e.g. LIMA_HOME) is propagated.
Example fix
// before
opts := &downloader.Options{}
res, err := opts.Download(ctx, "", "https://example.com/img.iso")
// after
opts := &downloader.Options{CacheDir: filepath.Join(home, ".cache", "lima")}
res, err := opts.Download(ctx, "", "https://example.com/img.iso") Defensive patterns
Strategy: validation
Validate before calling
if o.CacheDir == "" && local == "" {
return errors.New("cache-only download requires Options.CacheDir to be set")
} Try / catch
res, err := d.Download(ctx, local, url)
if err != nil && strings.Contains(err.Error(), "cache directory to be specified") {
return fmt.Errorf("configure CacheDir in downloader options: %w", err)
} Prevention
- Always set CacheDir when constructing downloader Options.
- Add a unit test asserting Options construction populates CacheDir.
- Propagate LIMA_HOME-derived paths into the downloader consistently.
When it happens
Trigger: Calling downloader.Download with local=="" while opts.cacheDir is empty — typically via DownloadFile or direct Download calls that omit CacheDir in the downloader Options and pass an empty local path.
Common situations: Constructing downloader.New() without setting CacheDir but intending cache-only lookups; tests/utilities that pass "" for local to mean "just use the cache".
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
- invalid digest in raw digest file %q: %w
- failed to read raw digest file %q: %w
- failed to convert image to raw: %w
- failed to open raw tmp file %q: %w
- failed to stat raw tmp file %q: %w
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/6a38e9b0faf1a579.
Report an issue: GitHub.