EllanJiang/GameFramework · error · GameFrameworkException
File system is not writable.
Error message
File system is not writable.
What it means
WriteFile(string name, byte[] buffer, int startIndex, int length) throws this GameFrameworkException when the file system was opened with FileSystemAccess.Read only. Writing requires the file system to have been created/opened with Write or ReadWrite access. The guard fires before any name or buffer validation.
Solutions
- Open the file system with FileSystemAccess.Write or FileSystemAccess.ReadWrite (e.g. via FileSystem.Create with access: FileSystemAccess.ReadWrite).
- If the file system is already created, check fs.Access (m_Access) before writing and route writes to a writable instance.
- Split usage: keep a read-only instance for shipped data and a separate ReadWrite instance for user-writable data.
Example fix
// before var fs = FileSystem.Create(fullPath, FileSystemAccess.Read, ...); fs.WriteFile(name, buffer, 0, buffer.Length); // throws // after var fs = FileSystem.Create(fullPath, FileSystemAccess.ReadWrite, ...); fs.WriteFile(name, buffer, 0, buffer.Length);
Defensive patterns
Strategy: validation
Validate before calling
if (fs.Access != FileSystemAccess.Write && fs.Access != FileSystemAccess.ReadWrite) throw new InvalidOperationException("File system opened read-only; cannot write."); Type guard
static bool IsWritable(FileSystem fs) => fs != null && (fs.Access == FileSystemAccess.Write || fs.Access == FileSystemAccess.ReadWrite);
Try / catch
try { fs.WriteFile(name, buffer, startIndex, length); } catch (GameFrameworkException ex) when (ex.Message == "File system is not writable.") { /* reopen with Write/ReadWrite access */ } Prevention
- Open with FileSystemAccess.ReadWrite whenever the same handle will read and write.
- Assert access mode once at startup, not at every write.
- Keep shipped read-only data and user data in separate file systems.
When it happens
Trigger: Opening a FileSystem (FileSystem.Create / LoadFileSystem or via the helper with access parameter) with FileSystemAccess.Read, then calling any WriteFile overload. Common when the same open handle is reused for both reads and writes.
Common situations: A config or download flag opens the package read-only (e.g. shipped game data) but update code later tries to write into it; sharing one FileSystem instance between a read path and a write path; access enum changed during a refactor.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Name ' ' is too long.
- Offset is invalid.
- Length is invalid.
- String ' ' is too long.
- Full path is invalid.
AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15).
Data as JSON: /api/errors/81ec0a5fbf2b2d8b.
Report an issue: GitHub.
Appendix: source
Thrown at GameFramework/FileSystem/FileSystem.cs:811
throw new GameFrameworkException("Buffer is invalid.");
}
return WriteFile(name, buffer, startIndex, buffer.Length - startIndex);
}
/// <summary>
/// 写入指定文件。
/// </summary>
/// <param name="name">要写入的文件名称。</param>
/// <param name="buffer">存储写入文件内容的二进制流。</param>
/// <param name="startIndex">存储写入文件内容的二进制流的起始位置。</param>
/// <param name="length">存储写入文件内容的二进制流的长度。</param>
/// <returns>是否写入指定文件成功。</returns>
public bool WriteFile(string name, byte[] buffer, int startIndex, int length)
{
if (m_Access != FileSystemAccess.Write && m_Access != FileSystemAccess.ReadWrite)
{
throw new GameFrameworkException("File system is not writable.");
}
if (string.IsNullOrEmpty(name))
{
throw new GameFrameworkException("Name is invalid.");
}
if (name.Length > byte.MaxValue)
{
throw new GameFrameworkException(Utility.Text.Format("Name '{0}' is too long.", name));
}
if (buffer == null)
{
throw new GameFrameworkException("Buffer is invalid.");
}
if (startIndex < 0 || length < 0 || startIndex + length > buffer.Length)View on GitHub (pinned to d0c010b051)