benbjohnson/litestream · error
invalid ltx path: %s
Error message
invalid ltx path: %s
What it means
parseLTXPath converts a NATS object key into (level, minTXID, maxTXID) and expects the layout `ltx/<level>/<minTXID>-<maxTXID>.ltx` (after stripping the configured Path prefix). This error means the object key does not match that layout, so it cannot be interpreted as an LTX segment.
Source
Thrown at nats/replica_client.go:264
return nil
}
// ltxPath returns the object path for an LTX file.
func (c *ReplicaClient) ltxPath(level int, minTXID, maxTXID ltx.TXID) string {
return litestream.LTXFilePath(c.Path, level, minTXID, maxTXID)
}
// parseLTXPath parses an LTX object path and returns level, minTXID, and maxTXID.
func (c *ReplicaClient) parseLTXPath(objPath string) (level int, minTXID, maxTXID ltx.TXID, err error) {
// Remove the base path prefix if present
if c.Path != "" && strings.HasPrefix(objPath, c.Path+"/") {
objPath = strings.TrimPrefix(objPath, c.Path+"/")
}
// Expected format: "ltx/<level>/<minTXID>-<maxTXID>.ltx"
parts := strings.Split(objPath, "/")
if len(parts) < 3 || parts[0] != "ltx" {
return 0, 0, 0, fmt.Errorf("invalid ltx path: %s", objPath)
}
// Parse level
if level, err = strconv.Atoi(parts[1]); err != nil {
return 0, 0, 0, fmt.Errorf("invalid level in path %s: %w", objPath, err)
}
// Parse filename (minTXID-maxTXID.ltx)
filename := parts[2]
minTXIDVal, maxTXIDVal, err := ltx.ParseFilename(filename)
if err != nil {
return 0, 0, 0, fmt.Errorf("invalid filename in path %s: %w", objPath, err)
}
return level, minTXIDVal, maxTXIDVal, nil
}
// LTXFiles returns an iterator of all LTX files on the replica for a given level.View on GitHub (pinned to 4ed7a308f6)
Solutions
- Inspect the offending object key in the bucket (`nats object ls backups`) and remove non-LTX objects
- Fix the `path` prefix in the litestream config so `ltx/...` keys parse after prefix stripping
- Ensure litestream (not other tools) owns this bucket — use a dedicated bucket
- If keys came from a legacy layout, re-snapshot with a full backup and `litestream reset`
Example fix
// config // before (prefix mismatch: objects stored under "litestream/ltx/...") url: "nats://host:4222/backups" // after path: "litestream" url: "nats://host:4222/backups"
Defensive patterns
Strategy: validation
Validate before calling
// validate object keys before parsing
parts := strings.Split(strings.TrimPrefix(key, prefix+"/"), "/")
if len(parts) < 3 || parts[0] != "ltx" {
log.Printf("skipping non-LTX object %q in replica bucket", key)
} Prevention
- Keep the replica bucket dedicated to litestream output
- Set the `path` config option correctly so prefix stripping yields `ltx/...` keys
- Audit bucket contents when sharing infrastructure with other tools
When it happens
Trigger: LTXFiles → parseLTXPath on an object whose key has fewer than 3 slash-separated parts or whose first part is not `ltx`: foreign objects uploaded to the bucket, wrong Path prefix in config, or legacy/differently-named keys.
Common situations: Users or other tools storing non-LTX objects in the replica bucket; misconfigured `path` prefix in litestream config so the prefix strip fails; buckets shared between different tooling; keys created by older litestream layouts.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid level in path %s: %w
- invalid NATS URL: %w
- invalid scheme for NATS replica: %s
- bucket required for NATS replica
- client-cert and client-key must both be specified for mutual
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/017f17b5b90cb461.
Report an issue: GitHub.