{"record":{"id":"26bf95d219e77e87","repo":"docker/compose","slug":"service-s-doesn-t-have-a-build-section-can-t-app","errorCode":null,"errorMessage":"service %s doesn't have a build section, can't apply %s on watch","messagePattern":"service (.+?) doesn't have a build section, can't apply (.+?) on watch","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compose/watch.go","lineNumber":425,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"resolving symlink for %q: %w\", project.WorkingDir, err)\n\t}\n\n\tfor i, trigger := range config.Watch {\n\t\tif !filepath.IsAbs(trigger.Path) {\n\t\t\ttrigger.Path = filepath.Join(baseDir, trigger.Path)\n\t\t}\n\t\tif p, err := filepath.EvalSymlinks(trigger.Path); err == nil {\n\t\t\t// this might fail because the path doesn't exist, etc.\n\t\t\ttrigger.Path = p\n\t\t}\n\t\ttrigger.Path = filepath.Clean(trigger.Path)\n\t\tif trigger.Path == \"\" {\n\t\t\treturn nil, errors.New(\"watch rules MUST define a path\")\n\t\t}\n\n\t\tif trigger.Action == types.WatchActionRebuild && service.Build == nil {\n\t\t\treturn nil, fmt.Errorf(\"service %s doesn't have a build section, can't apply %s on watch\", types.WatchActionRebuild, service.Name)\n\t\t}\n\t\tif trigger.Action == types.WatchActionSyncExec && len(trigger.Exec.Command) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"can't watch with action %q on service %s without a command\", types.WatchActionSyncExec, service.Name)\n\t\t}\n\n\t\tconfig.Watch[i] = trigger\n\t}\n\treturn &config, nil\n}\n\nfunc checkIfPathAlreadyBindMounted(watchPath string, volumes []types.ServiceVolumeConfig) bool {\n\tfor _, volume := range volumes {\n\t\tif volume.Bind != nil {\n\t\t\trelPath, err := filepath.Rel(volume.Source, watchPath)\n\t\t\tif err == nil && !strings.HasPrefix(relPath, \"..\") {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/compose/watch.go#L407-L443","documentation":"Thrown while Compose validates a service's `develop.watch` rules: a trigger uses `action: rebuild`, but the service has no `build:` section, so there is nothing to rebuild. The format arguments are swapped in the source, so the rendered message reads like `service rebuild doesn't have a build section, can't apply web on watch` — the first %s is actually the action and the second is the service name.","triggerScenarios":"Running `docker compose watch` (or `up --watch`) on a project where a service declares `develop: watch: [{action: rebuild, ...}]` but only defines `image:` with no `build:` block. Raised during config load in pkg/compose/watch.go before any watcher starts.","commonSituations":"Copy-pasting a watch section from a template into a service that pulls a prebuilt image; converting a build-based service to `image:` and forgetting to change the watch action to `sync`; using `rebuild` where `sync` + `exec` was intended.","solutions":["Add a `build:` section to the service so the rebuild action has a build context","Change the watch trigger action from `rebuild` to `sync` if the service runs a prebuilt image","Remove the rebuild watch rule for image-only services"],"exampleFix":"# before\nservices:\n  web:\n    image: nginx:alpine\n    develop:\n      watch:\n        - path: ./src\n          action: rebuild\n\n# after\nservices:\n  web:\n    build: ./src\n    develop:\n      watch:\n        - path: ./src\n          action: rebuild","handlingStrategy":"validation","validationCode":"# before running docker compose watch, assert every rebuild rule has a build section\npython3 - <<'EOF'\nimport yaml, sys\np = yaml.safe_load(open('compose.yaml'))\nfor name, svc in (p.get('services') or {}).items():\n    for rule in ((svc.get('develop') or {}).get('watch') or []):\n        if rule.get('action') == 'rebuild' and not svc.get('build'):\n            sys.exit(f\"service {name}: rebuild watch rule but no build section\")\nEOF","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep watch rules next to the build section they depend on when authoring services","Prefer `sync` for image-only services; reserve `rebuild` for services with a build context","Lint compose files in CI with `docker compose config` before deploying watch-based workflows"],"tags":["compose","watch","config","develop"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}