golang/go · error
Config.Importer.Import(%s) returned nil but no error
Error message
Config.Importer.Import(%s) returned nil but no error
What it means
Thrown by the types2 type checker's resolver when an installed Config.Importer's Import(path) method returns a nil *Package together with a nil error. The Go importer contract requires that a nil package always be accompanied by a non-nil error; returning both nil is a programmer error in the importer implementation. This guard converts that silent contract violation into an explicit BrokenImport so type checking can proceed with a synthetic fake package instead of panicking.
Source
Thrown at src/cmd/compile/internal/types2/resolver.go:158
check.error(pos, BadImportPath, "cannot use FakeImportC and go115UsesCgo together")
}
imp = NewPackage("C", "C")
imp.fake = true // package scope is not populated
imp.cgo = check.conf.go115UsesCgo
} else {
// ordinary import
var err error
if importer := check.conf.Importer; importer == nil {
err = fmt.Errorf("Config.Importer not installed")
} else if importerFrom, ok := importer.(ImporterFrom); ok {
imp, err = importerFrom.ImportFrom(path, dir, 0)
if imp == nil && err == nil {
err = fmt.Errorf("Config.Importer.ImportFrom(%s, %s, 0) returned nil but no error", path, dir)
}
} else {
imp, err = importer.Import(path)
if imp == nil && err == nil {
err = fmt.Errorf("Config.Importer.Import(%s) returned nil but no error", path)
}
}
// make sure we have a valid package name
// (errors here can only happen through manipulation of packages after creation)
if err == nil && imp != nil && (imp.name == "_" || imp.name == "") {
err = fmt.Errorf("invalid package name: %q", imp.name)
imp = nil // create fake package below
}
if err != nil {
check.errorf(pos, BrokenImport, "could not import %s (%s)", path, err)
if imp == nil {
// create a new fake package
// come up with a sensible package name (heuristic)
name := strings.TrimSuffix(path, "/")
if i := strings.LastIndex(name, "/"); i >= 0 {
name = name[i+1:]
}
imp = NewPackage(path, name)View on GitHub (pinned to b6b368adc5)
Solutions
- Fix the importer so Import never returns (nil, nil) — return a non-nil error whenever the package is nil
- If using a custom importer, verify every error path actually returns an error before returning a nil package
- Switch to an importer that implements ImporterFrom (ImportFrom) so the ImportFrom branch is taken instead
- Reproduce with a logging wrapper around the importer to find which import path triggers the nil/nil return
Example fix
// before
def (i *myImporter) Import(path string) (*types.Package, error) {
pkg := i.cache[path]
if pkg == nil {
return nil, nil // bug
}
return pkg, nil
}
// after
def (i *myImporter) Import(path string) (*types.Package, error) {
pkg := i.cache[path]
if pkg == nil {
return nil, fmt.Errorf("package %q not found", path)
}
return pkg, nil
} Defensive patterns
Strategy: validation
Validate before calling
// Wrap any custom importer to enforce the (pkg, err) contract:
type safeImporter struct{ inner types.Importer }
func (s safeImporter) Import(path string) (*types.Package, error) {
pkg, err := s.inner.Import(path)
if pkg == nil && err == nil {
return nil, fmt.Errorf("importer returned nil package without error for %q", path)
}
return pkg, err
}
// Use: conf.Importer = safeImporter{inner: myImporter} Type guard
// go has no sum type here; guard by interface satisfaction:
if _, ok := conf.Importer.(types2.ImporterFrom); !ok {
// Import() path will be used; ensure it never returns (nil,nil)
} Try / catch
// In Go, check both returns explicitly:
pkg, err := importer.Import(path)
if err != nil { return err }
if pkg == nil { return fmt.Errorf("nil package for %q", path) } Prevention
- Never let a custom Import/ImportFrom return (nil, nil)
- Wrap third-party importers with a contract-enforcing decorator
- Unit-test the importer against unresolved paths and assert an error is returned
When it happens
Trigger: Produced when check.conf.Importer is non-nil, does NOT satisfy ImporterFrom, and calling importer.Import(path) on some import path yields (nil, nil). Only reachable through go/types or cmd/compile/internal/types2 Config.Check / Importer usage with a custom or third-party importer.
Common situations: A hand-written types.Importer whose Import returns (nil, nil) on a missing/unresolved path instead of returning an error. Bug in a vendored importer shim. Mock importer used in tests that forgets to set an error.
Related errors
- invalid package name: %q
- can't resolve import %s
- can't resolve export %s
- non-file URL
- file URL missing path
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/5bd13091d12f74fb.
Report an issue: GitHub.