{"record":{"id":"6417e3b1497cdd10","repo":"docker/compose","slug":"unsupported-external-config-s","errorCode":null,"errorMessage":"unsupported external config %s","messagePattern":"unsupported external config (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compose/create.go","lineNumber":1169,"sourceCode":"\t}\n\treturn m, nil\n}\n\nfunc buildContainerConfigMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {\n\tmounts := map[string]mount.Mount{}\n\n\tconfigsBaseDir := \"/\"\n\tfor _, config := range s.Configs {\n\t\ttarget := config.Target\n\t\tif config.Target == \"\" {\n\t\t\ttarget = configsBaseDir + config.Source\n\t\t} else if !isAbsTarget(config.Target) {\n\t\t\ttarget = configsBaseDir + config.Target\n\t\t}\n\n\t\tdefinedConfig := p.Configs[config.Source]\n\t\tif definedConfig.External {\n\t\t\treturn nil, fmt.Errorf(\"unsupported external config %s\", definedConfig.Name)\n\t\t}\n\n\t\tif definedConfig.Driver != \"\" {\n\t\t\treturn nil, errors.New(\"Docker Compose does not support configs.*.driver\") //nolint:staticcheck\n\t\t}\n\t\tif definedConfig.TemplateDriver != \"\" {\n\t\t\treturn nil, errors.New(\"Docker Compose does not support configs.*.template_driver\") //nolint:staticcheck\n\t\t}\n\n\t\tif definedConfig.Environment != \"\" || definedConfig.Content != \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tif config.UID != \"\" || config.GID != \"\" || config.Mode != nil {\n\t\t\tlogrus.Warn(\"config `uid`, `gid` and `mode` are not supported, they will be ignored\")\n\t\t}\n\n\t\tbindMount, err := buildMount(p, types.ServiceVolumeConfig{","sourceCodeStart":1151,"sourceCodeEnd":1187,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/compose/create.go#L1151-L1187","documentation":"Returned when building container configs for a service that references a config declared with 'external: true'. Docker Compose (the Go v2 implementation) cannot materialize external configs the way Swarm does — it needs the config defined in the project (file, content, or environment) so it can mount it.","triggerScenarios":"A compose file where the top-level configs: section has an entry with external: true (or external with a name), and a service mounts that config; CreateContainer then hits this branch in the config loop.","commonSituations":"Porting a docker-stack/swarm YAML to compose v2; leftover external: from a Swarm deployment; configs created out-of-band with 'docker config create' expected to be reused.","solutions":["Remove 'external: true' and define the config inline (file:, content:, or environment:)","If the config was created out-of-band, point file: at the same source file instead","For Swarm-only workflows, keep using 'docker stack deploy' rather than compose"],"exampleFix":"# before\nconfigs:\n  mycert:\n    external: true\n# after\nconfigs:\n  mycert:\n    file: ./certs/server.pem","handlingStrategy":"validation","validationCode":"// preflight the compose model before Create/Up\nfor name, cfg := range project.Configs {\n    if cfg.External {\n        return fmt.Errorf(\"config %s is external; define it with file/content/environment\", name)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := compose.Up(ctx, ...); err != nil && strings.Contains(err.Error(), \"unsupported external config\") { /* rewrite config inline and retry */ }","preventionTips":["Lint compose files (docker compose config) in CI to catch external: entries","Keep Swarm stack files separate from compose v2 files","Prefer file: for static config data"],"tags":["configs","compose-file","swarm-migration"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}