AvaloniaUI/Avalonia · error · Error

StorageItem is not a writeable file

Error message

StorageItem is not a writeable file

What it means

Thrown by StorageItem.openWrite when the item has no handle or its kind is not 'file'. Writing requires a FileSystemFileHandle to call createWritable; a directory or a handleless item (e.g. a raw File or a well-known directory) is not writeable.

Source

Thrown at src/Browser/Avalonia.Browser/webapp/modules/storage/storageItem.ts:63

    public static async openRead(item: StorageItem): Promise<Blob> {
        if (item.file) {
            return item.file;
        }

        if (!item.handle || item.kind !== "file") {
            throw new Error("StorageItem is not a file");
        }

        await item.verifyPermissions("read");

        const file = await (item.handle as FileSystemFileHandle).getFile();
        return file;
    }

    public static async openWrite(item: StorageItem): Promise<FileSystemWritableFileStream> {
        if (!item.handle || item.kind !== "file") {
            throw new Error("StorageItem is not a writeable file");
        }

        await item.verifyPermissions("readwrite");

        return await (item.handle as FileSystemFileHandle).createWritable({ keepExistingData: false });
    }

    public static async getProperties(item: StorageItem): Promise<{ Size: number; LastModified: number; Type: string } | null> {
        // getFile can fail with an exception depending if we use polyfill with a save file dialog or not.
        try {
            const file = item.handle && "getFile" in item.handle
                ? await item.handle.getFile()
                : item.file;

            if (!file) {
                return null;
            }

View on GitHub (pinned to 11c5427268)

Solutions

  1. Acquire the item via the native file picker (showSaveFilePicker) so it carries a FileSystemFileHandle before writing.
  2. Guard with item.kind === 'file' && !!item.handle before openWrite.
  3. When the user must overwrite an existing picked File, prompt with showSaveFilePicker to get a writable handle.

Example fix

// before
const writable = await StorageItem.openWrite(item); // item from <input type=file>

// after
if (!item.handle || item.kind !== 'file') {
  const handle = await window.showSaveFilePicker();
  item = StorageItem.createFromHandle(handle);
}
const writable = await StorageItem.openWrite(item);
Defensive patterns

Strategy: validation

Validate before calling

if (!item.handle || item.kind !== 'file') {
  // acquire a writable handle via the native picker instead
  const handle = await window.showSaveFilePicker();
  item = StorageItem.createFromHandle(handle);
}

Type guard

function isWriteableFileItem(item: StorageItem): boolean {
  return item.kind === 'file' && !!item.handle;
}

Try / catch

try { return await StorageItem.openWrite(item); }
catch (e) {
  if (e instanceof Error && e.message.includes('writeable file')) { /* re-prompt for a save handle */ return null; }
  throw e;
}

Prevention

When it happens

Trigger: StorageItem.openWrite(item) where item.handle is undefined or item.kind !== 'file'. Most commonly calling openWrite on a StorageItem created from createFromFile (a read-only File with no handle) or on a directory item.

Common situations: Trying to save back to a File picked from an <input type=file> (no FileSystemFileHandle, so not writeable); writing to a directory handle; using the polyfill path where no native picker/granted handle exists.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/2cf457d1bc04a671. Report an issue: GitHub.