withastro/astro · error · AstroError
UnknownFilesystemError
UnknownFilesystemError
Error message
An unknown error occurred while reading or writing files to disk.
What it means
Thrown by MutableDataStore.writeAssetImports when writing the empty-asset-imports placeholder file ('export default new Map();') fails. The underlying fs error is attached as cause. This path runs when the store has zero asset imports and tries to persist the empty default export.
Source
Thrown at packages/astro/src/content/mutable-data-store.ts:134
const id = imageSrcToImportId(assetImport, typedEntry.filePath);
if (id) {
this.#assetImports.add(id);
}
}
}
}
}
}
async writeAssetImports(filePath: PathLike) {
this.#assetsFile = filePath;
this.#rebuildAssetImports();
if (this.#assetImports.size === 0) {
try {
await this.#writeFileAtomic(filePath, 'export default new Map();');
} catch (err) {
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
}
}
if (!this.#assetsDirty && existsSync(filePath)) {
return;
}
// Import the assets, with a symbol name that is unique to the import id. The import
// for each asset is an object with path, format and dimensions.
// We then export them all, mapped by the import id, so we can find them again in the build.
const imports: Array<string> = [];
const exports: Array<string> = [];
// Sort asset imports to ensure deterministic output across builds
const sortedAssetImports = [...this.#assetImports].sort();
sortedAssetImports.forEach((id, index) => {
const symbol = `__ASTRO_IMAGE_IMPORT_${index}`;
imports.push(`import ${symbol} from ${JSON.stringify(id)};`);
exports.push(`[${JSON.stringify(id)}, ${symbol}]`);
});View on GitHub (pinned to d081033d5f)
Solutions
- Check the cause field on the thrown error for the real OS error code (EACCES, ENOSPC, ENOENT).
- Ensure the .astro/ directory exists and is writable: rm -rf .astro and re-run.
- Run the build with adequate filesystem permissions and free disk space.
- If in CI, verify the working directory is writable and not on a read-only mount.
Defensive patterns
Strategy: try-catch
Validate before calling
import { existsSync, accessSync, constants } from 'node:fs';
import { dirname } from 'node:path';
function ensureWritableDir(p: string) {
const dir = dirname(p);
if (!existsSync(dir)) throw new Error(`missing dir ${dir}`);
accessSync(dir, constants.W_OK);
} Try / catch
try {
await store.writeAssetImports(assetsPath);
} catch (e) {
const cause = e instanceof AstroError ? e.cause : e;
if (cause && /EACCES|ENOENT|ENOSPC/.test((cause as Error).message)) {
// permissions/space/path issue - surface actionable hint
}
throw e;
} Prevention
- Verify .astro/ exists and is writable before building.
- Run builds under a user that owns the cache directory.
- Free disk/inode headroom before large builds.
- Avoid deleting .astro mid-build.
When it happens
Trigger: The atomic write helper (#writeFileAtomic) fails on the assets file path: permission denied, EACCES, disk full, the target directory was deleted, or the path is read-only.
Common situations: Build output directory (.astro/) is read-only or missing; running the build as a user without write permission to the project; CI environments where .astro was made immutable; disk-full or inode exhaustion; antivirus/SELinux blocking writes.
Related errors
- UnknownFilesystemError
- UnknownFilesystemError
- Failed to write lock file: ${message}
- CannotDetermineWeightAndStyleFromFontFile
- ID must be a non-empty string
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/9067ea2d9c9917f5.
Report an issue: GitHub.