{"record":{"id":"5c19593c59f4ba83","repo":"GoogleContainerTools/skaffold","slug":"post-sync-hooks-failed-for-artifact-q-w","errorCode":null,"errorMessage":"post-sync hooks failed for artifact %q: %w","messagePattern":"post-sync hooks failed for artifact %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/sync/sync.go","lineNumber":301,"sourceCode":"\t\tcopy = append(copy, k)\n\t}\n\tfor k := range item.Delete {\n\t\tdelete = append(delete, k)\n\t}\n\n\topts, err := hooks.NewSyncEnvOpts(item.Artifact, item.Image, copy, delete, *s.namespaces, s.kubectl.KubeContext)\n\tif err != nil {\n\t\treturn err\n\t}\n\thooksRunner := hooks.NewSyncRunner(s.kubectl, item.Artifact.ImageName, item.Image, *s.namespaces, s.formatter, item.Artifact.Sync.LifecycleHooks, opts)\n\tif err := hooksRunner.RunPreHooks(ctx, out); err != nil {\n\t\treturn fmt.Errorf(\"pre-sync hooks failed for artifact %q: %w\", item.Artifact.ImageName, err)\n\t}\n\tif err := s.sync(ctx, item); err != nil {\n\t\treturn err\n\t}\n\tif err := hooksRunner.RunPostHooks(ctx, out); err != nil {\n\t\treturn fmt.Errorf(\"post-sync hooks failed for artifact %q: %w\", item.Artifact.ImageName, err)\n\t}\n\treturn nil\n}\n\nfunc (s *PodSyncer) sync(ctx context.Context, item *Item) error {\n\tif len(item.Copy) > 0 {\n\t\tlog.Entry(ctx).Info(\"Copying files:\", item.Copy, \"to\", item.Image)\n\n\t\tif err := Perform(ctx, item.Image, item.Copy, s.copyFileFn, *s.namespaces, s.kubectl.KubeContext); err != nil {\n\t\t\treturn fmt.Errorf(\"copying files: %w\", err)\n\t\t}\n\t}\n\n\tif len(item.Delete) > 0 {\n\t\tlog.Entry(ctx).Info(\"Deleting files:\", item.Delete, \"from\", item.Image)\n\n\t\tif err := Perform(ctx, item.Image, item.Delete, s.deleteFileFn, *s.namespaces, s.kubectl.KubeContext); err != nil {\n\t\t\treturn fmt.Errorf(\"deleting files: %w\", err)","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/sync/sync.go#L283-L319","documentation":"PodSyncer.Sync runs post-sync lifecycle hooks after the file copy/delete completes. If RunPostHooks fails, Skaffold wraps the error with the artifact image name. Note the copy/delete already succeeded at this point — the synced state is in place but the hook (e.g. a restart or reload trigger) failed.","triggerScenarios":"Any `sync.lifecycleHooks.postSync` exec/container hook fails during a file-change sync: non-zero exit, kubectl exec/connect error, missing target container, or timeout.","commonSituations":"postSync container restart hook naming a container that doesn't exist in the pod; network/CNI issue making kubectl exec fail intermittently; hook command failing because the just-synced file is invalid (compile error picked up by reload command).","solutions":["Re-run the postSync command manually via kubectl exec to see the real failure output","Fix the postSync spec (containerName, command) in skaffold.yaml for the named artifact","If the hook depends on the synced files, validate the changed files locally (build/test) before saving them"],"exampleFix":"// before\npostSync:\n  - container: {containerName: sidecar-not-there, command: [\"kill\", \"-HUP\", \"1\"]}\n// after\npostSync:\n  - container: {containerName: app, command: [\"kill\", \"-HUP\", \"1\"]}","handlingStrategy":"try-catch","validationCode":"for _, h := range a.Sync.LifecycleHooks.PostSync {\n    if h.Container != nil && h.Container.ContainerName == \"\" { return errors.New(\"postSync container hook missing containerName\") }\n    if h.Exec != nil && len(h.Exec.Command) == 0 { return errors.New(\"empty postSync exec command\") }\n}","typeGuard":null,"tryCatchPattern":"err := s.Sync(ctx, out, names, item)\nif err != nil {\n    if strings.Contains(err.Error(), \"post-sync hooks failed\") {\n        log.Warnf(\"files synced but postSync hook failed (state is updated): %v\", err)\n        // treat as non-fatal if the hook is only a reload trigger\n        return nil\n    }\n    return err\n}","preventionTips":["Keep postSync hooks idempotent and tolerant of transient kubectl exec failures","Validate changed files (build/lint locally) so reload hooks don't fail on broken input","Verify containerName values against the deployed pod spec"],"tags":["skaffold","sync","hooks","kubectl"],"backgroundTag":"sync-hook-failed","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}