benbjohnson/litestream · error
invalid temp file name: %q
Error message
invalid temp file name: %q
What it means
tempFilenameFromCanonical derives a local temp-file name from a canonical SQLite file name by taking filepath.Base and rejecting names whose base is "." or a path separator. This error means the canonical name has no usable base component, so a deterministic temp file name cannot be built. It is raised before a FNV hash is computed.
Source
Thrown at vfs.go:379
})
return vfs.tempDir, vfs.tempDirErr
}
func (vfs *VFS) canonicalTempName(name string) string {
if name == "" {
return ""
}
name = filepath.Clean(name)
if name == "." || name == string(filepath.Separator) {
return ""
}
return name
}
func tempFilenameFromCanonical(canonical string) (string, error) {
base := filepath.Base(canonical)
if base == "." || base == string(filepath.Separator) {
return "", fmt.Errorf("invalid temp file name: %q", canonical)
}
h := fnv.New64a()
if _, err := h.Write([]byte(canonical)); err != nil {
return "", fmt.Errorf("hash temp name: %w", err)
}
return fmt.Sprintf("%s-%016x", base, h.Sum64()), nil
}
func (vfs *VFS) openTempFile(name string, flags sqlite3vfs.OpenFlag) (sqlite3vfs.File, sqlite3vfs.OpenFlag, error) {
dir, err := vfs.ensureTempDir()
if err != nil {
return nil, flags, err
}
deleteOnClose := flags&sqlite3vfs.OpenDeleteOnClose != 0 || name == ""
var f *os.File
var onClose func()
if name == "" {View on GitHub (pinned to 4ed7a308f6)
Solutions
- Remove trailing slashes from the database/journal path before opening it through the VFS.
- Pass a real file name, not a directory, to SQLite when using the litestream VFS.
- Log the offending canonical name (it is quoted in the error) and fix the code that generates it.
- If SQLite itself generates such names, capture a reproducible xOpen trace and report upstream.
Example fix
// before name := "file:/var/tmp/dbdir/" // base == "." // after name := "file:/var/tmp/dbdir/app.db" // base == "app.db"
Defensive patterns
Strategy: validation
Validate before calling
func validCanonical(name string) bool {
b := filepath.Base(name)
return b != "." && b != string(filepath.Separator) && name != ""
}
// call before opening: if !validCanonical(name) { fix path } Type guard
func isRealFilePath(p string) bool {
return filepath.Base(p) != "." && filepath.Base(p) != string(filepath.Separator)
} Prevention
- Strip trailing slashes from file paths/URIs before opening.
- Never pass directory paths as database names.
- Assert file-name validity in config loading, before SQLite sees it.
- Unit-test open paths that go through user-supplied config.
When it happens
Trigger: SQLite passes an unusual canonical name to xOpen that triggers openTempFile, and the name's filepath.Base evaluates to "." (e.g. name ends with a separator or is ".") or equals the OS separator.
Common situations: Constructing file URIs with trailing slashes ("file:/tmp/foo/") so the base collapses to "."; passing a directory instead of a file path; bugs in wrapper code that strip the file name and hand the VFS only a directory path.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- create temp dir for hydration: %w
- cannot delete vfs file
- hash temp name: %w
- temp file not tracked
- clear write buffer: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/f666ed8b22ea66e5.
Report an issue: GitHub.