{"record":{"id":"48c8058bb49214df","repo":"docker/compose","slug":"no-available-sync-implementation","errorCode":null,"errorMessage":"no available sync implementation","messagePattern":"no available sync implementation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compose/watch.go","lineNumber":127,"sourceCode":"\tw.stopFn = nil\n\terr := <-w.errCh\n\treturn err\n}\n\n// getSyncImplementation returns an appropriate sync implementation for the\n// project.\n//\n// Currently, an implementation that batches files and transfers them using\n// the Moby `Untar` API.\nfunc (s *composeService) getSyncImplementation(project *types.Project) (sync.Syncer, error) {\n\tvar useTar bool\n\tif useTarEnv, ok := os.LookupEnv(\"COMPOSE_EXPERIMENTAL_WATCH_TAR\"); ok {\n\t\tuseTar, _ = strconv.ParseBool(useTarEnv)\n\t} else {\n\t\tuseTar = true\n\t}\n\tif !useTar {\n\t\treturn nil, errors.New(\"no available sync implementation\")\n\t}\n\n\treturn sync.NewTar(project.Name, tarDockerClient{s: s}), nil\n}\n\nfunc (s *composeService) Watch(ctx context.Context, project *types.Project, options api.WatchOptions) error {\n\twait, err := s.watch(ctx, project, options)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn wait()\n}\n\ntype watchRule struct {\n\ttypes.Trigger\n\tinclude watch.PathMatcher\n\tignore  watch.PathMatcher\n\tservice string","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/compose/watch.go#L109-L145","documentation":"Compose watch's file sync currently has exactly one implementation: a tar-batching transfer via the Moby Untar API. The COMPOSE_EXPERIMENTAL_WATCH_TAR env var gates it; when parsed as false, getSyncImplementation has nothing left to return and errors out. This is effectively a kill-switch for sync, not a real selection mechanism.","triggerScenarios":"`docker compose watch` (with any service using a sync/sync_exec watch action) while COMPOSE_EXPERIMENTAL_WATCH_TAR is set to a falsey value (0, false, FALSE, no).","commonSituations":"Users toggling experimental env vars to work around watch issues and disabling the only sync backend; CI environments carrying COMPOSE_EXPERIMENTAL_WATCH_TAR=0 globally; stale advice in scripts from when multiple sync implementations existed.","solutions":["Unset the variable: `unset COMPOSE_EXPERIMENTAL_WATCH_TAR`","Set it explicitly to 1/true: `COMPOSE_EXPERIMENTAL_WATCH_TAR=1 docker compose watch`","If you only need rebuilds, change watch actions to `rebuild` which do not require the sync implementation"],"exampleFix":"# before\nCOMPOSE_EXPERIMENTAL_WATCH_TAR=0 docker compose watch\n# after\ndocker compose watch  # or COMPOSE_EXPERIMENTAL_WATCH_TAR=1","handlingStrategy":"validation","validationCode":"if [ -n \"$COMPOSE_EXPERIMENTAL_WATCH_TAR\" ] && ! [[ \"$COMPOSE_EXPERIMENTAL_WATCH_TAR\" =~ ^(1|t|T|true|TRUE)$ ]]; then\n  unset COMPOSE_EXPERIMENTAL_WATCH_TAR\nfi\ndocker compose watch","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not set COMPOSE_EXPERIMENTAL_WATCH_TAR=0 when using sync/sync_exec watch actions","Audit your shell profile and CI env for stale experimental compose variables"],"tags":["watch","sync","environment","experimental"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}