pocketbase/pocketbase · warning

file %d (%q): %w

Error message

file %d (%q): %w

What it means

Per-file failure entry when FileField deletes a record's files: fsys.Delete(path) failed with something other than filesystem.ErrNotFound. The error records the file's index in the record's filename list, the filename, and the wrapped storage error. These entries are accumulated (not returned immediately) and later joined into error 129.

Source

Thrown at core/field_file.go:606

		return filenames, err
	}
	defer fsys.Close()
	fsys.SetContext(ctx)

	var failures []error

	for i := len(filenames) - 1; i >= 0; i-- {
		filename := filenames[i]
		if filename == "" || strings.ContainsAny(filename, "/\\") {
			continue // empty or not a plain filename
		}

		path := record.BaseFilesPath() + "/" + filename

		err := fsys.Delete(path)
		if err != nil && !errors.Is(err, filesystem.ErrNotFound) {
			// store the delete error
			failures = append(failures, fmt.Errorf("file %d (%q): %w", i, filename, err))
		} else {
			// remove the deleted file from the list
			filenames = append(filenames[:i], filenames[i+1:]...)

			// try to delete the related file thumbs (if any)
			thumbsErr := fsys.DeletePrefix(record.BaseFilesPath() + "/thumbs_" + filename + "/")
			if len(thumbsErr) > 0 {
				app.Logger().Warn("Failed to delete file thumbs", "error", errors.Join(thumbsErr...))
			}
		}
	}

	if len(failures) > 0 {
		return filenames, fmt.Errorf("failed to delete all files: %w", errors.Join(failures...))
	}

	return nil, nil
}

View on GitHub (pinned to 5d217ddb50)

Solutions

  1. Check the wrapped error for the storage cause (permission, S3 access denied).
  2. For local storage, fix ownership/permissions on pb_data/storage recursively (chown -R appuser: pb_data).
  3. For S3, add s3:DeleteObject to the bucket policy for the configured credentials.
  4. Manually verify the file at pb_data/storage/<collection>/<record>/ exists if the error seems spurious.

Example fix

// before: running the server as root sometimes, creating root-owned uploads
// after: always run under the same user and fix existing files
// chown -R pbuser:pbuser pb_data
Defensive patterns

Strategy: fallback

Try / catch

_, err := field.DeleteFiles(ctx, app, record, names) // or record delete path
if err != nil {
    // entries carry index+filename; treat non-fatal for record deletion flows,
    // log and schedule a storage sweep instead of failing the delete
}

Prevention

When it happens

Trigger: Deleting a record (or removing files from a file field) where the underlying storage delete fails: permission denied on the local file, S3 delete error, or path issues. Only plain filenames without path separators are attempted; ErrNotFound is tolerated because the file may already be gone.

Common situations: pb_data/storage files owned by root after running under a different user; S3 bucket policy forbidding DeleteObject; a file lock on Windows; the record's storage folder having been manually moved or renamed.

Related errors


AI-assisted analysis of pocketbase/pocketbase@5d217ddb50 (2026-08-15). Data as JSON: /api/errors/3b2c541000c49254. Report an issue: GitHub.