`FileSystem.FileHandle.writeFromOffset` ignores its offset and writes at position 0
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 13
- Forks
- 6
- Avg merge
- 5d 20h
- Merged PRs (30d)
- 3
Description
Found against:* gren 0.6.6, gren-lang/core 7.4.2, gren-lang/node 6.1.3, node 22
Reproduction: in https://github.com/gilramir/gren-bug-reports in 2026-09-11-writefromoffset; ./run.sh prints the figure below.
Reproduction
Write ten As, open the file for writing, put two Zs at offset 5, read it
back:
FileSystem.writeFile fsPermission (Bytes.fromString "AAAAAAAAAA") path
|> Task.andThen
(\_ -> FileHandle.openForWrite fsPermission FileHandle.ExpectExisting path)
|> Task.andThen
(\fh ->
FileHandle.writeFromOffset fh 5 (Bytes.fromString "ZZ")
|> Task.andThen (\_ -> FileHandle.close fh)
)
|> Task.andThen (\_ -> FileSystem.readFile fsPermission path)
wrote "ZZ" at offset 5 into "AAAAAAAAAA"
expected AAAAAZZAAA
got ZZAAAAAAAA
The "ZZ"'s were written at offset 0.
Reason
writeFromOffset takes the offset as a plain Int:
{-| Write bytes into a specific location of a file.
-}
writeFromOffset : WriteableFileHandle a -> Int -> Bytes -> Task FileSystem.Error (WriteableFileHandle a)
writeFromOffset =
Gren.Kernel.FileSystem.writeFromOffset
The kernel function behind it reads that argument as a record:
var _FileSystem_writeFromOffset = F3(function (fh, options, bytes) {
return __Scheduler_binding(function (callback) {
_FileSystem_writeHelper(
fh,
bytes,
0,
bytes.byteLength,
options.__$offset,
callback,
);
});
});
options is a number, so options.__$offset is undefined. That is handed to
fs.write as its position, where undefined means "wherever the file
currently is" — which for a freshly opened handle is 0.
So the offset argument has no effect at all. Every writeFromOffset writes
where write would have written.
readFromOffset beside it does take a record, { offset, length }, and is
correct. The kernel function for the write looks like a copy of the read's that
kept the record access after the Gren signature stopped passing one.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the Gren.Kernel.FileSystem.writeFromOffset entry point and compare its argument handling with the adjacent readFromOffset implementation. Run the reproduction's ./run.sh first; done means writing two bytes at offset 5 produces AAAAAZZAAA rather than ZZAAAAAAAA.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100