astral-sh/ruff · error · io::Error
The system does not support writing files
Error message
The system does not support writing files
What it means
This is a Rust `std::io::Error` with `ErrorKind::Unsupported` produced by ty's `ProjectDatabase::writable_system()` when the underlying `System` does not implement the `WritableSystem` trait (`system().as_writable()` returns `None`). It surfaces when a caller (e.g. the ty server or `ty_python_semantic::fixes::fix_all`) attempts to write a file to disk, but the database was constructed with a read-only or virtual system that only supports reading. The library throws it to make write capability an explicit, checked property of the system abstraction instead of assuming writes always work.
Source
Thrown at crates/ty_project/src/db.rs:668
ty_vendored::file_system()
}
fn system(&self) -> &dyn System {
&*self.system
}
fn files(&self) -> &Files {
&self.files
}
}
#[salsa::db]
impl salsa::Database for ProjectDatabase {}
impl DbWithWritableSystem for ProjectDatabase {
fn writable_system(&self) -> ruff_db::system::Result<&dyn WritableSystem> {
self.system().as_writable().ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::Unsupported,
"The system does not support writing files",
)
})
}
}
#[salsa::db]
impl Db for ProjectDatabase {
fn project(&self) -> Project {
self.project.unwrap()
}
fn uv_environments(&self) -> &UvEnvironments {
&self.uv_environments
}
fn dyn_clone(&self) -> Box<dyn Db> {View on GitHub (pinned to 15f3fe6b15)
Solutions
- Use a system that supports writing (e.g. `OsSystem`) when constructing the `ProjectDatabase` if you intend to write or apply fixes.
- If using a custom `System`, implement `as_writable()` to return a `Some(&dyn WritableSystem)` adapter (see `crates/ruff_db/src/system/os.rs:195`).
- Before calling write-dependent APIs (like `fix_all`), check writability up front via `db.system().as_writable().is_some()` and skip or surface a read-only message instead.
- If you only need analysis without writes, avoid invoking write paths so the read-only system is never asked to write.
- Keep the virtual/read-only system for tests but switch to `OsSystem` in production configuration.
Example fix
// before: read-only (virtual) system injected, writes fail let system: DynSystem = test::TestSystem::new().into(); let db = ProjectDatabase::new(module_db, system); fix_all(&mut db)?; // io::Error (Unsupported) // after: use a writable OS-backed system let system: DynSystem = OsSystem::new(cwd).into(); let db = ProjectDatabase::new(module_db, system); fix_all(&mut db)?;
Defensive patterns
Strategy: validation
Validate before calling
// Check writability before calling write-dependent APIs
if db.system().as_writable().is_none() {
eprintln!("Operation skipped: this system does not support writing files");
return Ok(());
} Type guard
fn is_writable(db: &dyn DbWithWritableSystem) -> bool {
db.system().as_writable().is_some()
} Try / catch
// Rust: match on the io::Error kind rather than any error
match db.writable_system() {
Ok(system) => { /* use system to write */ }
Err(e) if e.kind() == std::io::ErrorKind::Unsupported => {
// read-only environment: degrade gracefully
eprintln!("Cannot write: system is read-only");
}
Err(e) => return Err(e.into()),
} Prevention
- Construct ProjectDatabase with a writable system whenever fix/apply operations may run.
- Expose a `--read-only` awareness in your tooling: disable fixers instead of letting them fail.
- When implementing the `System` trait, always decide deliberately what `as_writable()` returns and test both branches.
- Check `as_writable().is_some()` before offering fix-alls or write features in IDE/server integrations.
- Keep write paths behind a capability check so read-only virtual systems used in tests never reach them.
When it happens
Trigger: Calling any operation that goes through `DbWithWritableSystem::writable_system()` — such as applying code fixes (`fix_all`) that write files, or server write operations — while the `ProjectDatabase` was built over a system whose `as_writable()` returns `None` (e.g. the read-only test/memory system in `ruff_db::system::test`, or a custom read-only `System` implementation). The real `OsSystem` always returns `Some(self)`, so this only fires with non-OS systems.
Common situations: Running ty embedded in a tool or test harness that injects a virtual in-memory system for hermetic analysis; configuring the LSP server with a read-only system; implementing a custom `System` trait implementation without overriding `as_writable()` to return a writable adapter; calling fix/apply-diagnostics APIs in a read-only preview mode.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- extra use-def data should have been retained
- System should be writable
- should be set because `extract_if` only yields elements with
- Should only ever pass a positive integer to `from_nonnegativ
- argument index should be valid
AI-assisted analysis of astral-sh/ruff@15f3fe6b15 (2026-09-13).
Data as JSON: /api/errors/2c9c78f3d1c1bc02.
Report an issue: GitHub.