opentofu/opentofu · error
invalid root module source address: %w
Error message
invalid root module source address: %w
What it means
The new-runtime scaffolding converts the root module directory into a module source address by prefixing './' for relative paths and calling addrs.ParseModuleSource, which was designed for module block source arguments, not arbitrary filesystem paths (the comment in the code says exactly this). The error wraps a parse failure: the directory path contains characters that cannot be interpreted as a local source address, such as ':' (which makes the path look like a registry/remote address, including Windows drive letters), '?' or '#'.
Source
Thrown at internal/command/temp_new_runtime.go:107
Provisioners: staticPlugins,
Workspace: workspace,
}
// The new config-loading system wants to work in terms of module source
// addresses rather than raw local filenames, so we'll ask the
// addrs package to parse the path we were given. We need to adjust
// a little though, because this function was designed for parsing
// the "source" argument in a module block, not a plain filepath.
// We should add a function in package addrs that's actually intended for
// turning arbitrary filesystem paths in to addrs.LocalSource in the long
// run, but this will do for now.
configDir := root.SourceDir
if !filepath.IsAbs(configDir) {
configDir = "." + string(filepath.Separator) + configDir
}
rootModuleSource, err := addrs.ParseModuleSource(configDir)
if err != nil {
diags = diags.Append(fmt.Errorf("invalid root module source address: %w", err))
return nil, diags
}
configCall := &eval.ConfigCall{
RootModuleSource: rootModuleSource,
InputValues: inputValues,
AllowImpureFunctions: false,
EvalContext: evalCtx,
}
configInst, moreDiags := eval.NewConfigInstance(ctx, configCall)
diags = diags.Append(moreDiags)
if moreDiags.HasErrors() {
return nil, diags
}
return configInst, diags
}
// newRuntimeModules is an implementation of [eval.ExternalModules] that makesView on GitHub (pinned to 3561785c48)
Solutions
- Run the command from a path without ':', '?', '#' characters — on Windows, try invoking from a relative path so the './' prefix branch is used
- Check the -chdir argument and current directory for stray address-like characters
- Move or symlink the checkout into a plain path (e.g. C:\src\mod or ~/src/mod) and retry
- If it fails on a clean POSIX path, report it — the code itself flags this path-to-address conversion as a stopgap
Example fix
# before (Windows absolute path is parsed as a remote address) tofu test -chdir C:\proj\mod # after cd C:\proj\mod && tofu test
Defensive patterns
Strategy: validation
Validate before calling
abs, err := filepath.Abs(configDir)
if err != nil {
return err
}
for _, bad := range []string{":", "?", "#"} {
if strings.Contains(abs, bad) {
// ParseModuleSource would reject this as a non-local address
return fmt.Errorf("path %q contains %q and cannot be used as a local module source", abs, bad)
}
} Try / catch
rootModuleSource, err := addrs.ParseModuleSource(configDir)
if err != nil {
// recover by retrying with a cleaned relative path from the module root
if rel, relErr := filepath.Rel(moduleRoot, configDir); relErr == nil {
rootModuleSource, err = addrs.ParseModuleSource("." + string(filepath.Separator) + rel)
}
if err != nil {
diags = diags.Append(fmt.Errorf("invalid root module source address: %w", err))
}
} Prevention
- Invoke tofu from inside the module directory (relative configDir) so the ./-prefixed local path is used
- Keep checkout paths free of ':', '?', '#' — especially on Windows drive-letter layouts
- Avoid directory names that resemble registry or remote source addresses
When it happens
Trigger: Absolute Windows paths (C:\... do not start with ./ so they are parsed as remote addresses and rejected); directory names containing ':', '?', '#', or other address syntax; a root.SourceDir that is empty or degenerate after -chdir handling.
Common situations: Running the new-runtime-based commands (tofu test and similar) on Windows from drive-letter paths; checkouts under directories with unusual characters; odd -chdir arguments.
Related errors
- Failed to initialize config loader: %w
- unable to locate module: %w
- NewResourceConfigShimmed given %#v; an object type is requir
- Unlocking the state file on TencentCloud cos backend failed:
- state name not allow to be empty
AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15).
Data as JSON: /api/errors/95dedfafe6b456d8.
Report an issue: GitHub.