You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[windows] file-system-access: async ops invoked on pending IAsyncOperation; enumeration/size/sync members broken #11613
@nativescript/core 9.1.3 (pkg.pr.new runtime abae298/cbec98bb), packaged WinUI 3 MSIX (org.octanexplat.windows61), Windows 11 x64, {N} Windows runtime alpha.
Defects verified on the packaged runtime
packages/core/file-system/file-system-access.windows.js has two defect classes, verified at runtime (not source inspection):
1. Async methods invoked on the pending IAsyncOperation (E_FAIL)
deleteFile, deleteFolder, and rename call StorageFile.GetFileFromPathAsync(path) / StorageFolder.GetFolderFromPathAsync(path) synchronously, then invoke DeleteAsync()/RenameAsync() on the returned operation object rather than the resolved entity:
// deleteFile (windows):StorageFile.GetFileFromPathAsync(path).DeleteAsync()// pending op, not the file
Runtime result: File.remove() rejects Error: Unspecified error (HRESULT 0x80004005) and removeSync() silently swallows it — deletes never happen. Verified on MSIX 1.0.0.204/205/209/212; workaround is toPromise(GetFileFromPathAsync(path)) then toPromise(file.DeleteAsync()), which deletes correctly.
2. Fake-sync .done() pattern on a projection that only exposes then
Folder.getEntities/eachEntity → StorageFolder.GetFolderFromPathAsync(...).done is not a function (the code calls op.done(...)).
getFileSize → file.size silently returns 0.
readTextSync/writeTextSync/readBufferSync/writeBufferSync → call .done() and return before completion, so sync reads always yield ''/undefined.
File.lastModified resolves but the try/catch fallback can hide a real failure behind new Date().
Net working surface on the pinned runtime: File.exists, Folder.exists, path joins, and the real async text/buffer IO (readText/writeText/readBuffer/writeBuffer/appendText). Every delete, rename, enumeration, size, and sync-read member is broken or silent-wrong.
Happy to share the qualification fixture that produced the evidence.
Real-world impact — the broken members sit in the standard {N} file API that ordinary app code uses everywhere:
Cache eviction silently never happens.file.remove()/removeSync() throwing (or being swallowed) means thumbnail/media/document caches grow unboundedly — any app doing "delete the stale cached file" leaks disk on every run.
file.tmp → file.ext download/rename fails. Download managers and save flows that write to a temp name then rename() to the final name — a near-universal pattern — break with E_FAIL.
Directory listing is dead.Folder.getEntities()/eachEntity() is how apps show "recent files", enumerate a documents/exports folder, or sum cache sizes. It throws on call.
file.size returning 0 breaks progress and quota checks. Download/upload progress (% of file), "file too large" validation, and storage-usage displays all silently report wrong data — worse than an error, since it looks like a successful 0.
readTextSync returning '' silently corrupts config reads. A quick sync settings/feature-flag read yields an empty string rather than throwing, so callers proceed with empty data as if the file were blank.
Effectively: any {N} app that lists a folder, deletes a temp/cache file, renames a downloaded file, or reads file size hits a wall on Windows today — the only safe paths are exists, joins, and the async text/buffer methods.
Activity
aleclarson commentedon Nov 4, 2026
Real-world impact — the broken members sit in the standard
{N}file API that ordinary app code uses everywhere:file.remove()/removeSync()throwing (or being swallowed) means thumbnail/media/document caches grow unboundedly — any app doing "delete the stale cached file" leaks disk on every run.file.tmp → file.extdownload/rename fails. Download managers and save flows that write to a temp name thenrename()to the final name — a near-universal pattern — break with E_FAIL.Folder.getEntities()/eachEntity()is how apps show "recent files", enumerate a documents/exports folder, or sum cache sizes. It throws on call.file.sizereturning0breaks progress and quota checks. Download/upload progress (% of file), "file too large" validation, and storage-usage displays all silently report wrong data — worse than an error, since it looks like a successful0.readTextSyncreturning''silently corrupts config reads. A quick sync settings/feature-flag read yields an empty string rather than throwing, so callers proceed with empty data as if the file were blank.Effectively: any {N} app that lists a folder, deletes a temp/cache file, renames a downloaded file, or reads file size hits a wall on Windows today — the only safe paths are
exists, joins, and the async text/buffer methods.