{"record":{"id":"44e979a16b664513","repo":"docker/cli","slug":"undefined-volume-q","errorCode":null,"errorMessage":"undefined volume %q","messagePattern":"undefined volume %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/compose/convert/volume.go","lineNumber":63,"sourceCode":"\t\treturn mount.Mount{}, errors.New(\"images options are incompatible with type volume\")\n\t}\n\tif volume.Tmpfs != nil {\n\t\treturn mount.Mount{}, errors.New(\"tmpfs options are incompatible with type volume\")\n\t}\n\tif volume.Bind != nil {\n\t\treturn mount.Mount{}, errors.New(\"bind options are incompatible with type volume\")\n\t}\n\tif volume.Cluster != nil {\n\t\treturn mount.Mount{}, errors.New(\"cluster options are incompatible with type volume\")\n\t}\n\t// Anonymous volumes\n\tif volume.Source == \"\" {\n\t\treturn result, nil\n\t}\n\n\tstackVolume, exists := stackVolumes[volume.Source]\n\tif !exists {\n\t\treturn mount.Mount{}, fmt.Errorf(\"undefined volume %q\", volume.Source)\n\t}\n\n\tresult.Source = namespace.Scope(volume.Source)\n\tresult.VolumeOptions = &mount.VolumeOptions{}\n\n\tif volume.Volume != nil {\n\t\tresult.VolumeOptions.NoCopy = volume.Volume.NoCopy\n\t\tresult.VolumeOptions.Subpath = volume.Volume.Subpath\n\t}\n\n\tif stackVolume.Name != \"\" {\n\t\tresult.Source = stackVolume.Name\n\t}\n\n\t// External named volumes\n\tif stackVolume.External.External {\n\t\treturn result, nil\n\t}","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/compose/convert/volume.go#L45-L81","documentation":"Returned by handleVolumeToMount when a service mounts a named volume whose source is not in the top-level volumes map and is not anonymous (volume.go:61-64). A non-anonymous volume mount must be declared at the top level (or be external) for the converter to build its Mount.","triggerScenarios":"A service volume entry of type volume (the default) with a non-empty `source` that has no entry in the stack volumes map. Reached at volume.go:62 when stackVolumes[volume.Source] is absent.","commonSituations":"Mounting `myvol:/data` but never declaring `volumes: myvol:`; renamed a volume inconsistently across files; forgot `external: true` for a pre-existing volume.","solutions":["Declare the volume in the top-level `volumes:` block.","If it already exists in Docker, mark it `external: true`.","For an anonymous volume, omit the source (left of the colon)."],"exampleFix":"// before\nservices:\n  db:\n    image: postgres\n    volumes: [pgdata:/var/lib/postgresql/data]\n// after\nservices:\n  db:\n    image: postgres\n    volumes: [pgdata:/var/lib/postgresql/data]\nvolumes:\n  pgdata:","handlingStrategy":"validation","validationCode":"func validateNamedVolumes(cfg *composetypes.Config) error {\n    for _, svc := range cfg.Services {\n        for _, v := range svc.Volumes {\n            if v.Type != \"volume\" && v.Type != \"\" { continue }\n            if v.Source == \"\" { continue } // anonymous\n            if _, ok := cfg.Volumes[v.Source]; !ok {\n                return fmt.Errorf(\"undefined volume %q\", v.Source)\n            }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare every named volume source in the top-level volumes block.","Use external: true for pre-existing volumes.","Omit the source for truly anonymous volumes."],"tags":["compose","convert","volumes","undefined"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}