{"record":{"id":"2d145123d1db626d","repo":"benbjohnson/litestream","slug":"cannot-specify-url-path-for-sftp-replica","errorCode":null,"errorMessage":"cannot specify url & path for sftp replica","messagePattern":"cannot specify url & path for sftp replica","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream/main.go","lineNumber":1805,"sourceCode":"\t\t}\n\t\tif client.Path == \"\" {\n\t\t\tclient.Path = strings.TrimPrefix(path.Clean(u.Path), \"/\")\n\t\t}\n\t}\n\n\t// Ensure required settings are set.\n\tif client.Bucket == \"\" {\n\t\treturn nil, fmt.Errorf(\"bucket required for abs replica\")\n\t}\n\n\treturn client, nil\n}\n\n// newSFTPReplicaClientFromConfig returns a new instance of sftp.ReplicaClient built from config.\nfunc newSFTPReplicaClientFromConfig(c *ReplicaConfig, _ *litestream.Replica) (_ *sftp.ReplicaClient, err error) {\n\t// Ensure URL & constituent parts are not both specified.\n\tif c.URL != \"\" && c.Path != \"\" {\n\t\treturn nil, fmt.Errorf(\"cannot specify url & path for sftp replica\")\n\t} else if c.URL != \"\" && c.Host != \"\" {\n\t\treturn nil, fmt.Errorf(\"cannot specify url & host for sftp replica\")\n\t}\n\n\thost, user, password, path := c.Host, c.User, c.Password, c.Path\n\n\t// Apply settings from URL, if specified.\n\tif c.URL != \"\" {\n\t\tu, err := url.Parse(c.URL)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Only apply URL parts to field that have not been overridden.\n\t\tif host == \"\" {\n\t\t\thost = u.Host\n\t\t}\n\t\tif user == \"\" && u.User != nil {","sourceCodeStart":1787,"sourceCodeEnd":1823,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/main.go#L1787-L1823","documentation":"newSFTPReplicaClientFromConfig rejects replica configs that supply both the combined 'url' field and the individual 'path' field. The URL is meant to fully describe connection details; mixing it with separate constituent fields is ambiguous, so startup fails with this validation error.","triggerScenarios":"An sftp replica config sets c.URL (e.g. 'sftp://user@host/backup') and also sets c.Path (e.g. path: /backup) at the same time.","commonSituations":"Merging an existing per-field sftp config with a new URL-based example copied from docs; a templated config that always emits 'path:' even when url is provided.","solutions":["Remove the 'path' field from the sftp replica config and keep only 'url'","Or remove 'url' and specify host/user/path fields individually","Encode the desired path inside the URL (sftp://user@host/<path>) instead of a separate key"],"exampleFix":"# before\n- type: sftp\n  url: sftp://user@host/backup\n  path: /backup\n# after\n- type: sftp\n  url: sftp://user@host/backup","handlingStrategy":"validation","validationCode":"if rep.Type == \"sftp\" && rep.URL != \"\" && rep.Path != \"\" {\n    return fmt.Errorf(\"sftp replica %s: url and path are mutually exclusive\", rep.Name)\n}","typeGuard":null,"tryCatchPattern":"if err := litestream.NewReplicaClientFromConfig(cfg, rep); err != nil {\n    if strings.Contains(err.Error(), \"cannot specify url & path for sftp\") {\n        // sanitize config: drop path when url is set\n    }\n}","preventionTips":["Choose one config style per replica: url OR discrete fields","Lint configs to reject url+path combos for sftp/webdav/abs","Keep documentation examples single-style"],"tags":["config","sftp","litestream","validation"],"backgroundTag":"conflicting-config-options","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}