lima-vm/lima · error
field `%s.host` must be an absolute path, but is %#q
Error message
field `%s.host` must be an absolute path, but is %#q
What it means
Validate() requires CopyToHost rules to use an absolute host-side path: if HostFile is non-empty it must satisfy filepath.IsAbs() (host OS semantics, validate.go:398-400). The destination on the host machine must be a fully qualified path so the copy target is unambiguous.
Source
Thrown at pkg/limayaml/validate.go:399
if rule.Reverse && rule.GuestSocket == "" {
errs = errors.Join(errs, fmt.Errorf("field `%s.reverse` must be %t", field, false))
}
if rule.Reverse && rule.HostSocket == "" {
errs = errors.Join(errs, fmt.Errorf("field `%s.reverse` must be %t", field, false))
}
// Not validating that the various GuestPortRanges and HostPortRanges are not overlapping. Rules will be
// processed sequentially and the first matching rule for a guest port determines forwarding behavior.
}
for i, rule := range y.CopyToHost {
field := fmt.Sprintf("CopyToHost[%d]", i)
if rule.GuestFile != "" {
if !path.IsAbs(rule.GuestFile) {
errs = errors.Join(errs, fmt.Errorf("field `%s.guest` must be an absolute path, but is %#q", field, rule.GuestFile))
}
}
if rule.HostFile != "" {
if !filepath.IsAbs(rule.HostFile) {
errs = errors.Join(errs, fmt.Errorf("field `%s.host` must be an absolute path, but is %#q", field, rule.HostFile))
}
}
}
if y.VMType != nil && *y.VMType == limatype.HCS {
if y.HostResolver.Enabled != nil && *y.HostResolver.Enabled && len(y.DNS) > 0 {
errs = errors.Join(errs, errors.New("field `dns` must be empty when field `HostResolver.Enabled` is true"))
}
} else {
if HostResolverEnabled(y) && len(y.DNS) > 0 {
errs = errors.Join(errs, errors.New("field `dns` must be empty when field `HostResolver.Enabled` is true"))
}
}
err := validateNetwork(y)
if err != nil {
errs = errors.Join(errs, err)
}View on GitHub (pinned to dd909d0973)
Solutions
- Use an absolute host path (e.g. /home/user/copy.txt); expand ~ yourself in the template.
- On the host side, filepath.IsAbs is platform-specific — on Windows use a drive-qualified path (C:\...).
- Pre-validate with `limactl validate` before limactl start.
Example fix
# before
copyToHost:
- guest: /var/log/app.log
host: logs/app.log
# after
copyToHost:
- guest: /var/log/app.log
host: /home/me/logs/app.log Defensive patterns
Strategy: validation
Validate before calling
for i, r := range cfg.CopyToHost {
if r.HostFile != "" && !filepath.IsAbs(r.HostFile) {
return fmt.Errorf("CopyToHost[%d].host must be absolute: %q", i, r.HostFile)
}
} Type guard
func absHostPath(p string) bool { return p != "" && filepath.IsAbs(p) } Try / catch
if err := limayaml.Validate(y, "strict"); err != nil {
return fmt.Errorf("copyToHost host path must be absolute: %w", err)
} Prevention
- Expand ~ and env vars yourself before putting the host path in the template.
- On Windows use drive-qualified absolute paths.
- Generate host destinations from absolute config values, not relative defaults.
When it happens
Trigger: limayaml.Validate() (via limactl validate/edit/start/restart/clone/rename/template tooling) sees CopyToHost[i].HostFile set to a relative path like "out.txt" or "./tmp/x".
Common situations: Writing `host: ~/copy.txt` expecting shell tilde expansion; template reuse across machines where a relative destination seemed convenient; programmatically generated rules defaulting to relative output names.
Related errors
- field `%s.guest` must be an absolute path, but is %#q
- currently Windows guest is only supported on [%#q, %#q]; got
- field `os` must be one of %#q; got %#q
- field `arch` must be one of %v; got %#q
- field `user.shell` must be one of %v for Windows guest, got
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/4753fd27454690f9.
Report an issue: GitHub.