lima-vm/lima · error
unexpected plist format: missing root dict
Error message
unexpected plist format: missing root dict
What it means
parseDiskutilImageAttachOutput validates that the parsed plist has the expected structure: a root dictionary containing a `system-entities` array of disk entities. This error means the XML parsed fine but the root dict is missing, so diskutil returned an unexpected plist shape. It guards against indexing into an absent structure.
Source
Thrown at pkg/imgutil/nativeimgutil/asifutil/asif_darwin.go:90
return nil
}
type AttachedDisk struct {
Disk string // whole disk device, e.g. "disk4" (GUID_partition_scheme)
Container string // APFS container partition, e.g. "disk4s2" (Apple_APFS)
Data string // data volume device, e.g. "disk7s5"
}
// parseDiskutilImageAttachOutput parses the output of `diskutil image attach -plist -nomount <disk>`
// and returns the attached disk information.
func parseDiskutilImageAttachOutput(xmlStr string) (*AttachedDisk, error) {
var p plist.Plist
if err := xml.Unmarshal([]byte(xmlStr), &p); err != nil {
return nil, fmt.Errorf("failed to unmarshal xml: %w", err)
}
if p.Value.Dict == nil {
return nil, errors.New("unexpected plist format: missing root dict")
}
seVal, ok := p.Value.Dict["system-entities"]
if !ok || len(seVal.Array) == 0 {
return nil, errors.New("unexpected plist format: missing system-entities array")
}
result := &AttachedDisk{}
for _, devEnt := range seVal.Array {
devDict := devEnt.Dict
if devDict == nil {
continue
}
devEntry, hasDevEntry := devDict["dev-entry"]
if !hasDevEntry || devEntry.String == nil || *devEntry.String == "" {
continue
}
if hint, ok := devDict["content-hint"]; ok && hint.String != nil {View on GitHub (pinned to dd909d0973)
Solutions
- Dump the plist output and compare its root type (dict vs array) against expectations
- Update the parser/plist mapping for the current macOS schema
- Check macOS version compatibility; adapt parsing per version if needed
- Treat the attach as failed and surface the raw output for diagnosis
Example fix
// before
if p.Value.Dict == nil {
return nil, errors.New("unexpected plist format: missing root dict")
}
// after (tolerate array-root plists)
if p.Value.Dict == nil && len(p.Value.Array) == 0 {
return nil, fmt.Errorf("unexpected plist format: root is neither dict nor array: %T", p.Value)
} Defensive patterns
Strategy: type-guard
Validate before calling
// preflight: structural check after unmarshal is inherent; validate expected keys before use
if p.Value == nil || p.Value.Dict == nil { return errors.New("plist root is not a dict") } Type guard
func hasRootDict(p *plist.Plist) bool { return p != nil && p.Value != nil && p.Value.Dict != nil } Try / catch
disk, err := asifutil.DiskutilImageAttachNoMount(path)
if err != nil {
if strings.Contains(err.Error(), "unexpected plist format") {
log.Printf("diskutil plist schema differs on this macOS; inspect raw output")
}
return err
} Prevention
- Test the parser against plists from all supported macOS versions
- Check the root plist type (dict vs array) before accessing keys
- Surface the raw plist in errors so schema drift is diagnosable
When it happens
Trigger: DiskutilImageAttachNoMount gets a plist whose root is an array (not a dict) or otherwise lacks a top-level dict — e.g. a different plist schema on another macOS version, or an error plist from diskutil.
Common situations: macOS version changed the `diskutil image attach -plist` schema; diskutil returned a plist describing something else than attached image entities; middleware/logging wrappers altered the output shape.
Related errors
- failed to unmarshal xml: %w
- invalid plist: top-level value is not a dict
- invalid plist: IORegistryEntryChildren not found or empty
- invalid plist: IOPlatformUUID not found in any child of IORe
- invalid date value: %w
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/d77eb3c4323bd59d.
Report an issue: GitHub.