{"record":{"id":"06487bdebe5b51d8","repo":"GoogleContainerTools/skaffold","slug":"opening-s-w-06487b","errorCode":null,"errorMessage":"opening %s: %w","messagePattern":"opening (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/event/v2/event.go","lineNumber":322,"sourceCode":"\t\t\t}\n\t\t\tev.state.DebuggingContainers = ev.state.DebuggingContainers[:n]\n\t\t}\n\t\tev.stateLock.Unlock()\n\t}\n\tev.logEvent(event)\n}\n\n// SaveEventsToFile saves the current event log to the filepath provided\nfunc SaveEventsToFile(fp string) error {\n\thandler.logLock.Lock()\n\t// Ensure that the filepath provided has the directories available when attemping to save the file.\n\tdir := filepath.Dir(fp)\n\tif err := os.MkdirAll(dir, 0700); err != nil {\n\t\treturn fmt.Errorf(\"unable to create directory %q: %w\", dir, err)\n\t}\n\tf, err := os.OpenFile(fp, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"opening %s: %w\", fp, err)\n\t}\n\tdefer f.Close()\n\tmarshaller := jsonpb.Marshaler{}\n\tfor _, ev := range handler.eventLog {\n\t\tcontents := bytes.NewBuffer([]byte{})\n\t\tif err := marshaller.Marshal(contents, ev); err != nil {\n\t\t\treturn fmt.Errorf(\"marshalling event: %w\", err)\n\t\t}\n\t\tif _, err := f.WriteString(contents.String() + \"\\n\"); err != nil {\n\t\t\treturn fmt.Errorf(\"writing string: %w\", err)\n\t\t}\n\t}\n\thandler.logLock.Unlock()\n\treturn nil\n}\n\n// SaveLastLog writes the output from the previous run to the specified filepath\nfunc SaveLastLog(fp string) error {","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/event/v2/event.go#L304-L340","documentation":"In the v2 event package, after directory creation succeeds, SaveEventsToFile opens the file with O_APPEND|O_WRONLY|O_CREATE (mode 0600). Failures are wrapped as 'opening %s'. The directory exists at this point, so the problem is with the file itself.","triggerScenarios":"The target path resolves to an existing directory (EISDIR); the parent is unwritable despite existing (EACCES); path exceeds NAME_MAX; the target is on a read-only filesystem where MkdirAll succeeded because the directory already existed but creating a new file inside fails (EROFS).","commonSituations":"Passing a directory path without a filename; on read-only filesystems where the directory already exists so MkdirAll succeeds but opening a new file fails; SELinux/AppArmor policies blocking creation.","solutions":["Append a filename if the destination is a directory path","Check that the filesystem is not read-only (mount | grep <path>) and pick a writable location","Verify write permission on the directory for the current user (ls -ld)","Inspect the wrapped syscall error for the precise errno"],"exampleFix":"// before\nv2event.SaveEventsToFile(\"/mnt/ro-volume/logs/\")\n// after\nv2event.SaveEventsToFile(\"/mnt/rw-volume/logs/events.json\")","handlingStrategy":"fallback","validationCode":"if info, err := os.Stat(fp); err == nil && info.IsDir() {\n    return fmt.Errorf(\"v2 event log path %q is a directory\", fp)\n}","typeGuard":null,"tryCatchPattern":"if err := v2event.SaveEventsToFile(fp); err != nil {\n    if strings.Contains(err.Error(), \"opening \") {\n        fallback := filepath.Join(os.TempDir(), \"skaffold-v2-events.json\")\n        log.Warnf(\"falling back to %s: %v\", fallback, err)\n        return v2event.SaveEventsToFile(fallback)\n    }\n    return err\n}","preventionTips":["Always pass a complete file path including a filename","Prefer writable locations: os.TempDir() or an explicitly mounted volume","Confirm the filesystem is mounted read-write before saving","Check for MAC/security policies (SELinux, AppArmor) blocking file creation in the target directory"],"tags":["filesystem","events","v2","open-file"],"backgroundTag":"permission-denied","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"}