golang/go · error
Config.Importer.ImportFrom(%s, %s, 0) returned nil but no er
Error message
Config.Importer.ImportFrom(%s, %s, 0) returned nil but no error
What it means
When the type checker's Config.Importer implements the ImporterFrom interface, it calls ImportFrom(path, dir, 0). If the importer returns (nil, nil) — a nil package with no error — this violates the importer contract. A nil package must always be accompanied by an error explaining why the import failed. This error is synthesized by the type checker to flag the contract violation.
Source
Thrown at src/cmd/compile/internal/types2/resolver.go:153
}
// no package yet => import it
if path == "C" && (check.conf.FakeImportC || check.conf.go115UsesCgo) {
if check.conf.FakeImportC && check.conf.go115UsesCgo {
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)View on GitHub (pinned to b6b368adc5)
Solutions
- Fix the custom importer to always return a non-nil error when the package is nil
- Use importer.Default() or go/packages instead of a custom implementation
- Add a defensive guard in the importer: if pkg == nil && err == nil { err = fmt.Errorf("import %q failed", path) }
- Write unit tests for the custom importer that verify it never returns (nil, nil)
Example fix
// before — buggy custom importer
func (m *MyImporter) ImportFrom(path, dir string, mode types.ImportMode) (*types.Package, error) {
pkg := m.cache[path]
if pkg == nil {
return nil, nil // BUG: contract violation
}
return pkg, nil
}
// after — fixed
func (m *MyImporter) ImportFrom(path, dir string, mode types.ImportMode) (*types.Package, error) {
pkg := m.cache[path]
if pkg == nil {
return nil, fmt.Errorf("package %q not found in cache", path)
}
return pkg, nil
} Defensive patterns
Strategy: validation
Validate before calling
// Wrap a custom importer to enforce the (nil package => non-nil error) 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 for %q without error", path)
}
return pkg, err
}
func (s *safeImporter) ImportFrom(path, dir string, mode types.ImportMode) (*types.Package, error) {
if imp, ok := s.inner.(types.ImporterFrom); ok {
pkg, err := imp.ImportFrom(path, dir, mode)
if pkg == nil && err == nil {
return nil, fmt.Errorf("ImportFrom returned nil package for %q without error", path)
}
return pkg, err
}
return s.Import(path)
}
// Usage: conf.Importer = &safeImporter{inner: myCustomImporter} Type guard
// Verify a custom importer satisfies the contract in tests
func assertImporterContract(imp types.Importer) error {
// Test with a path that should not resolve
_, err := imp.Import("github.com/nonexistent/pkg/that/does/not/exist")
// If err is nil and we get here, check if we got a nil package
// (the real test is that Import never returns (nil, nil))
if err == nil {
// If no error for a nonexistent package, the importer is too permissive
// but that's not a contract violation per se
}
return nil
} Prevention
- Always return a non-nil error from custom Importer implementations when the package is nil
- Wrap custom importers with a safeImporter guard that enforces the contract
- Write unit tests that call Import with non-existent paths and verify an error is returned
- Prefer using importer.Default() or go/packages over custom importer implementations
When it happens
Trigger: A custom types.Importer implementation whose ImportFrom method returns (nil, nil) for a not-found or error case instead of returning a proper error. Incomplete or buggy mock importer implementations in tests. Importers that swallow errors internally and return nil.
Common situations: Custom importer implementations in static analysis tools that have bugs in error handling. Mock importers in unit tests that don't properly simulate the error contract. Importers that check a cache and return nil on miss without falling through to actual resolution.
Related errors
- empty string
- invalid character %#U
- Config.Importer not installed
- cannot instantiate non-generic %s: has no type parameters
- cannot instantiate %s: got %d type arguments but have %d typ
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/5f1b25a960094e65.
Report an issue: GitHub.