{"record":{"id":"9bb5381b13e50813","repo":"vxcontrol/pentagi","slug":"failed-to-create-parent-directory-for-s-w","errorCode":null,"errorMessage":"failed to create parent directory for '%s': %w","messagePattern":"failed to create parent directory for '(.+?)': %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/flowfiles/files.go","lineNumber":415,"sourceCode":"\t\tcase tar.TypeDir:\n\t\t\tif err := os.MkdirAll(entryPath, 0755); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create directory '%s': %w\", entryPath, err)\n\t\t\t}\n\t\tcase tar.TypeReg, tar.TypeRegA:\n\t\t\tif hdr.Size < 0 {\n\t\t\t\treturn fmt.Errorf(\"tar entry '%s' has invalid size %d\", hdr.Name, hdr.Size)\n\t\t\t}\n\t\t\tfilesCount++\n\t\t\tif filesCount > MaxPullFiles {\n\t\t\t\treturn fmt.Errorf(\"tar archive exceeds maximum file count of %d\", MaxPullFiles)\n\t\t\t}\n\t\t\ttotalSize += hdr.Size\n\t\t\tif totalSize > MaxPullTotalSize {\n\t\t\t\treturn fmt.Errorf(\"tar archive exceeds maximum total size of %d bytes\", MaxPullTotalSize)\n\t\t\t}\n\n\t\t\tif err := os.MkdirAll(filepath.Dir(entryPath), 0755); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create parent directory for '%s': %w\", entryPath, err)\n\t\t\t}\n\n\t\t\tf, err := os.OpenFile(entryPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create file '%s': %w\", entryPath, err)\n\t\t\t}\n\t\t\t_, copyErr := io.CopyN(f, tr, hdr.Size)\n\t\t\tf.Close()\n\t\t\tif copyErr != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to write file '%s': %w\", entryPath, copyErr)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc ZipDirectory(w io.Writer, dirPath string) (err error) {","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/flowfiles/files.go#L397-L433","documentation":"Before writing each regular file, ExtractTar creates its parent directory with os.MkdirAll(filepath.Dir(entryPath), 0755). This error wraps that failure. entryPath has passed cleaning and containment checks, so causes are environmental: filesystem permissions, conflicts, or space.","triggerScenarios":"os.MkdirAll fails for a nested entry's parent while extracting via PullFlowFiles: destDir read-only, a regular file already occupies a parent-path component (ENOTDIR), path too long (ENAMETOOLONG), or disk full.","commonSituations":"Deeply nested archives exceeding filesystem path limits; re-extraction over a previous partial extraction where files collide with directory paths; container volumes owned by a different UID.","solutions":["Clear the destination directory before re-extracting so stale files don't shadow directory paths.","Check the wrapped errno: ENOSPC → free disk; EACCES → fix volume ownership/permissions; ENAMETOOLONG → flatten archive paths on the producer side.","Ensure destDir exists and is writable by the process user before calling ExtractTar.","Avoid extremely deep directory nesting when building the archive."],"exampleFix":"// before\nerr := flowfiles.ExtractTar(rc, destDir)\n// after\nos.RemoveAll(destDir) // fresh extraction target\nif err := os.MkdirAll(destDir, 0o755); err != nil { return err }\nerr := flowfiles.ExtractTar(rc, destDir)","handlingStrategy":"validation","validationCode":"info, err := os.Stat(destDir)\nif err != nil || !info.IsDir() {\n    return fmt.Errorf(\"destDir must exist as a writable directory\")\n}\nprobe, err := os.MkdirTemp(destDir, \".wprobe-*\")\nif err != nil {\n    return fmt.Errorf(\"destDir not writable: %w\", err)\n}\nos.Remove(probe)","typeGuard":null,"tryCatchPattern":"err := flowfiles.ExtractTar(rc, destDir)\nif err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) {\n        switch {\n        case errors.Is(pe.Err, syscall.ENOSPC):\n            return fmt.Errorf(\"destination disk full: %w\", err)\n        case errors.Is(pe.Err, syscall.EACCES), errors.Is(pe.Err, syscall.EROFS):\n            return fmt.Errorf(\"destination volume not writable: %w\", err)\n        case errors.Is(pe.Err, syscall.ENAMETOOLONG):\n            return fmt.Errorf(\"archive paths too long for target fs: %w\", err)\n        }\n    }\n    return err\n}","preventionTips":["Extract into a clean, freshly created directory per request to avoid stale-file/path collisions.","Keep archive directory nesting shallow to stay under NAME_MAX limits.","Verify destination volume permissions and free space before large extractions."],"tags":["filesystem","tar","extract","mkdir"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}