{"record":{"id":"f3ff3445433d0837","repo":"docker/cli","slug":"undefined-config-q","errorCode":null,"errorMessage":"undefined config %q","messagePattern":"undefined config %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/compose/convert/service.go","lineNumber":302,"sourceCode":"// and a set of compose Config specs, and creates the swarm ConfigReferences\n// required by the service. Unlike convertServiceSecrets, this takes the whole\n// ServiceConfig, because some Configs may be needed as a result of other\n// fields (like CredentialSpecs).\n//\n// TODO: fix configs API so that ConfigsAPIClient is not required here\nfunc convertServiceConfigObjs(\n\tctx context.Context,\n\tapiClient client.ConfigAPIClient,\n\tnamespace Namespace,\n\tservice composetypes.ServiceConfig,\n\tconfigSpecs map[string]composetypes.ConfigObjConfig,\n) ([]*swarm.ConfigReference, error) {\n\trefs := []*swarm.ConfigReference{}\n\n\tlookup := func(key string) (composetypes.FileObjectConfig, error) {\n\t\tconfigSpec, exists := configSpecs[key]\n\t\tif !exists {\n\t\t\treturn composetypes.FileObjectConfig{}, fmt.Errorf(\"undefined config %q\", key)\n\t\t}\n\t\treturn composetypes.FileObjectConfig(configSpec), nil\n\t}\n\tfor _, config := range service.Configs {\n\t\tobj, err := convertFileObject(namespace, composetypes.FileReferenceConfig(config), lookup)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tfile := swarm.ConfigReferenceFileTarget(obj.File)\n\t\trefs = append(refs, &swarm.ConfigReference{\n\t\t\tFile:       &file,\n\t\t\tConfigName: obj.Name,\n\t\t})\n\t}\n\n\t// finally, after converting all file objects, create any\n\t// Runtime-type configs that are needed. these are configs that are not","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/compose/convert/service.go#L284-L320","documentation":"Returned by the config lookup closure inside convertServiceConfigObjs when a config referenced by a service is absent from the top-level configSpecs map (service.go:300-303). Compose configs (Swarm configs) must be declared before use.","triggerScenarios":"A service's `configs:` list references a config not declared in the top-level `configs:` block; the lookup at service.go:301 returns false.","commonSituations":"Config mounted into a service but never declared; renamed a config in only one location; intended to use an external Swarm config but forgot `external: true`.","solutions":["Add the config under the top-level `configs:` key (file-backed or external).","If it already exists in Swarm, declare it `external: true` with its real name.","Fix the service's config name to match an existing declaration."],"exampleFix":"// before\nservices:\n  web:\n    image: nginx\n    configs:\n      - site.conf\n// after\nservices:\n  web:\n    image: nginx\n    configs:\n      - site.conf\nconfigs:\n  site.conf:\n    file: ./site.conf","handlingStrategy":"validation","validationCode":"func validateConfigsDeclared(cfg *composetypes.Config) error {\n    for _, svc := range cfg.Services {\n        for _, c := range svc.Configs {\n            if _, ok := cfg.Configs[c.Source]; !ok {\n                return fmt.Errorf(\"undefined config %q\", c.Source)\n            }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pair every service `configs:` entry with a top-level `configs:` declaration.","Use external: true for configs already in Swarm.","Lint compose files in CI before deploy."],"tags":["compose","convert","configs","swarm","undefined"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}