{"record":{"id":"63fff159bad79814","repo":"golang-migrate/migrate","slug":"source-driver-invalid-url-scheme","errorCode":null,"errorMessage":"source driver: invalid URL scheme","messagePattern":"source driver: invalid URL scheme","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"source/driver.go","lineNumber":83,"sourceCode":"\tReadUp(version uint) (r io.ReadCloser, identifier string, err error)\n\n\t// ReadDown returns the DOWN migration body and an identifier that helps\n\t// finding this migration in the source for a given version.\n\t// If there is no down migration available for this version,\n\t// it must return os.ErrNotExist.\n\t// Do not start reading, just return the ReadCloser!\n\tReadDown(version uint) (r io.ReadCloser, identifier string, err error)\n}\n\n// Open returns a new driver instance.\nfunc Open(url string) (Driver, error) {\n\tu, err := nurl.Parse(url)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif u.Scheme == \"\" {\n\t\treturn nil, fmt.Errorf(\"source driver: invalid URL scheme\")\n\t}\n\n\tdriversMu.RLock()\n\td, ok := drivers[u.Scheme]\n\tdriversMu.RUnlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"source driver: unknown driver '%s' (forgotten import?)\", u.Scheme)\n\t}\n\n\treturn d.Open(url)\n}\n\n// Register globally registers a driver.\nfunc Register(name string, driver Driver) {\n\tdriversMu.Lock()\n\tdefer driversMu.Unlock()\n\tif driver == nil {\n\t\tpanic(\"Register driver is nil\")","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/source/driver.go#L65-L101","documentation":"Raised by source.Open in source/driver.go when the parsed migration source URL has an empty URL scheme. The driver registry is keyed by scheme, so without a scheme the library cannot select a source driver and refuses to proceed.","triggerScenarios":"Calling source.Open (or migrate.New with a source URL string) with a URL that has no 'scheme://' prefix, e.g. Open('github.com/user/repo') instead of Open('github://user:token@github.com/user/repo'), or a URL built by string concatenation that lost its prefix.","commonSituations":"Hand-written config files where the scheme was accidentally dropped, environment variables expanded to empty (missing MIGRATE_SOURCE env prefix), or URLs copied from docs with the scheme omitted.","solutions":["Prefix the URL with its scheme, e.g. 'github://', 'file://', 's3://'","Verify the env var or config value supplying the URL is not empty/truncated","Log or print the URL right before source.Open to confirm what is actually passed"],"exampleFix":"// before\nsource.Open(\"github.com/user/repo/migrations\")\n// after\nsource.Open(\"github://user:token@github.com/user/repo/migrations\")","handlingStrategy":"validation","validationCode":"u, err := url.Parse(sourceURL)\nif err != nil {\n    return fmt.Errorf(\"bad source url: %w\", err)\n}\nif u.Scheme == \"\" {\n    return fmt.Errorf(\"source url %q missing scheme (want e.g. github://, file://)\", sourceURL)\n}","typeGuard":"func hasScheme(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && u.Scheme != \"\"\n}","tryCatchPattern":"d, err := source.Open(sourceURL)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid URL scheme\") {\n        return fmt.Errorf(\"check source URL %q: %w\", sourceURL, err)\n    }\n    return err\n}","preventionTips":["Always store full driver-qualified URLs including scheme://","Validate URLs at config load time, before calling Open","Keep source URLs in dedicated, clearly named config keys"],"tags":["url","configuration","source-driver"],"backgroundTag":"invalid-url-scheme","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}