hashicorp/nomad · warning
can't seek to offset %d: %w
Error message
can't seek to offset %d: %w
What it means
AllocDir.ReadAt fails when os.Seek to the requested offset on the opened alloc-dir file returns an error (e.g. offset beyond file size or an I/O error); the underlying seek error is wrapped and returned to the caller of the file-read endpoint.
Source
Thrown at client/allocdir/alloc_dir.go:510
if strings.HasSuffix(path, ".json") {
contentType = "application/json"
}
return contentType
}
// ReadAt returns a reader for a file at the path relative to the alloc dir
func (a *AllocDir) ReadAt(path string, offset int64) (io.ReadCloser, error) {
sanitizedPath, err := a.sanitizePath(path)
if err != nil {
return nil, err
}
f, err := os.Open(sanitizedPath)
if err != nil {
return nil, err
}
if _, err := f.Seek(offset, 0); err != nil {
return nil, fmt.Errorf("can't seek to offset %d: %w", offset, err)
}
return f, nil
}
// BlockUntilExists blocks until the passed file relative the allocation
// directory exists. The block can be cancelled with the passed context.
func (a *AllocDir) BlockUntilExists(ctx context.Context, path string) (chan error, error) {
sanitizedPath, err := a.sanitizePath(path)
if err != nil {
return nil, err
}
// Get the path relative to the alloc directory
watcher := getFileWatcher(sanitizedPath)
returnCh := make(chan error, 1)
t := &tomb.Tomb{}
go func() {
<-ctx.Done()View on GitHub (pinned to 482b49bf1a)
Solutions
- Check the offset is >= 0 and the target is a regular file before calling ReadAt
- Handle the wrapped seek error by re-statting the file and restarting at offset 0
- Avoid pointing the file API at non-seekable files (pipes, sockets, devices)
- Refresh stale offsets after the file has been rotated or truncated
Example fix
// before
f, err := allocDir.ReadAt("task/app/log", staleOffset)
// after
fi, _ := os.Stat("task/app/log")
off := staleOffset
if !fi.Mode().IsRegular() || off > fi.Size() {
off = 0
}
f, err := allocDir.ReadAt("task/app/log", off) Defensive patterns
Strategy: validation
Validate before calling
fi, err := os.Stat(path)
if err != nil || !fi.Mode().IsRegular() {
return fmt.Errorf("not a seekable regular file")
}
if offset < 0 || offset > fi.Size() {
offset = 0
} Try / catch
f, err := allocDir.ReadAt(relPath, off)
if err != nil && strings.Contains(err.Error(), "can't seek to offset") {
f, err = allocDir.ReadAt(relPath, 0) // restart from beginning
} Prevention
- Validate offsets come from a current stat, not stale state
- Never point the file API at pipes/sockets/devices
- Reset offset to 0 after file rotation/truncation
When it happens
Trigger: Calling ReadAt with a negative offset, or an offset beyond what the filesystem/file supports (e.g. past the end on a special file such as a pipe, device, or FIFO that is not seekable).
Common situations: Log/EOF-following logic computing an offset from a previous snapshot of a file replaced by a special file; offset from stale state after file truncation on filesystems that reject out-of-range seeks; reading non-regular files (sockets/pipes) created inside the alloc dir.
Related errors
- failed to rewind snapshot: %v
- failed to rewind temp snapshot: %v
- unable to read rooted allocation directory
- Couldn't copy %q to %q: %w
- error writing to file %q: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/d1b8830218fc0699.
Report an issue: GitHub.