Tencent/WeKnora · error

failed to open source file: %w

Error message

failed to open source file: %w

What it means

CopyFile fails to open the source file (os.Open(srcResolved)) and wraps the OS error. This means the source path does not exist, is not readable by the process, or is a directory. The copy never starts in this case; no destination file is created.

Source

Thrown at internal/application/service/file/local.go:195

	}

	// Build destination path with the knowledge-owned layout.
	dir := filepath.Join(s.baseDir, fmt.Sprintf("%d", tenantID), knowledgeID)
	if _, err := secutils.SafePathUnderBase(s.baseDir, dir); err != nil {
		logger.Errorf(ctx, "Path traversal denied for CopyFile dir: %v", err)
		return "", fmt.Errorf("invalid path: %w", err)
	}
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return "", fmt.Errorf("failed to create directory: %w", err)
	}

	ext := filepath.Ext(srcPath)
	filename := fmt.Sprintf("%d%s", time.Now().UnixNano(), ext)
	dstPath := filepath.Join(dir, filename)

	src, err := os.Open(srcResolved)
	if err != nil {
		return "", fmt.Errorf("failed to open source file: %w", err)
	}
	defer src.Close()

	dst, err := os.Create(dstPath)
	if err != nil {
		return "", fmt.Errorf("failed to create destination file: %w", err)
	}
	defer dst.Close()

	if _, err := io.Copy(dst, src); err != nil {
		return "", fmt.Errorf("failed to copy file content: %w", err)
	}

	relPath, _ := filepath.Rel(s.baseDir, dstPath)
	newPath := localScheme + filepath.ToSlash(relPath)
	logger.Infof(ctx, "Copied local file %s to %s", srcPath, newPath)
	return newPath, nil
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Log/inspect the wrapped error: ENOENT means the file is missing — verify srcPath exists with `stat` before calling CopyFile.
  2. If the source was on a temp/ephemeral volume, persist uploads to the durable baseDir first, or re-upload the original from the client.
  3. Fix file permissions or run the service as a user with read access to the source path.
  4. Guard the caller: only pass paths previously returned by this file service's Save/Upload methods, and check existence beforehand.

Example fix

// before
src, err := os.Open(srcResolved)
if err != nil {
    return "", fmt.Errorf("failed to open source file: %w", err)
}
// after
if _, err := os.Stat(srcResolved); errors.Is(err, os.ErrNotExist) {
    return "", fmt.Errorf("source file does not exist: %s", srcResolved)
}
src, err := os.Open(srcResolved)
if err != nil {
    return "", fmt.Errorf("failed to open source file: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

func ensureSourceReadable(srcPath string) error {
    fi, err := os.Stat(srcPath)
    if err != nil {
        return fmt.Errorf("source missing: %w", err)
    }
    if fi.IsDir() {
        return fmt.Errorf("source is a directory: %s", srcPath)
    }
    f, err := os.Open(srcPath)
    if err != nil {
        return fmt.Errorf("source not readable: %w", err)
    }
    f.Close()
    return nil
}
// call ensureSourceReadable(srcResolved) before CopyFile

Type guard

func fileExistsReadable(path string) bool {
    fi, err := os.Stat(path)
    return err == nil && fi.Mode().IsRegular()
}

Try / catch

newPath, err := svc.CopyFile(ctx, srcPath, tenantID, knowledgeID)
var perr *fs.PathError
if errors.As(err, &perr) && errors.Is(perr.Err, fs.ErrNotExist) {
    // stale reference: re-upload or restore source, then retry once
    if restoreErr := restoreSource(ctx, srcPath); restoreErr == nil {
        newPath, err = svc.CopyFile(ctx, srcPath, tenantID, knowledgeID)
    }
}
if err != nil {
    return fmt.Errorf("copy failed: %w", err)
}

Prevention

When it happens

Trigger: Calling CopyFile with srcPath pointing to a deleted/moved file, a file stored with a different naming scheme, a symlink target that vanished, or a file with permissions that deny read access to the service user.

Common situations: Uploading/app referencing a file that was garbage-collected or on a temporary volume that was cleaned; wrong path passed by an upstream caller (e.g. DB row stores a stale path); container image changes removed previously present files; NFS/object-store mount not mounted so files 'disappear'.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/d67a7cbe6cbd8ab9. Report an issue: GitHub.