dagger/dagger · error
SDK module %q has no source
Error message
SDK module %q has no source
What it means
Thrown by installedSDKSourceForModule in core/schema/workspace_sdk.go when a module entry matched as an SDK (by key or as-sdk name) has an empty effective source: moduleEntrySourceWithPin(entry) (source + optional @pin) returns "". An SDK install must point at a module source (local path or git ref with pin); without one Dagger cannot resolve where the SDK's module lives.
Source
Thrown at core/schema/workspace_sdk.go:243
}
matches = append(matches, moduleName)
}
sort.Strings(matches)
switch len(matches) {
case 0:
return "", workspace.ModuleEntry{}, "", fmt.Errorf("%q is not installed as an SDK in this workspace; run `dagger sdk install %s` first", name, name)
case 1:
entry := cfg.Modules[matches[0]]
return installedSDKSourceForModule(matches[0], entry)
default:
return "", workspace.ModuleEntry{}, "", fmt.Errorf("SDK name %q is ambiguous: matches modules.%s.as-sdk; choose a unique as-sdk.name", name, strings.Join(matches, ".as-sdk, modules."))
}
}
func installedSDKSourceForModule(moduleName string, entry workspace.ModuleEntry) (string, workspace.ModuleEntry, string, error) {
source := moduleEntrySourceWithPin(entry)
if source == "" {
return "", workspace.ModuleEntry{}, "", fmt.Errorf("SDK module %q has no source", moduleName)
}
return moduleName, entry, source, nil
}
func moduleEntrySourceWithPin(entry workspace.ModuleEntry) string {
return sourceWithPin(entry.Source, entry.Pin)
}
func resolvedModuleEntrySourceWithPin(configDir string, entry workspace.ModuleEntry) string {
return sourceWithPin(workspace.ResolveModuleEntrySource(configDir, entry.Source), entry.Pin)
}
func moduleEntrySourceWithPinRelativeTo(configDir, targetDir string, entry workspace.ModuleEntry) (string, error) {
if !workspace.IsLocalRef(entry.Source, "") {
return moduleEntrySourceWithPin(entry), nil
}
source := workspace.ResolveModuleEntrySource(configDir, entry.Source)
rel, err := filepath.Rel(targetDir, source)View on GitHub (pinned to 82ba2681db)
Solutions
- Add the missing `source` field to the module entry in dagger.json (local path or remote ref).
- Re-run `dagger sdk install <name>` so Dagger rewrites the entry with a proper source and pin.
- Restore the source value from version control (git diff/checkout dagger.json) if a merge or edit dropped it.
- Remove the broken entry entirely if it is stale, then reinstall the SDK.
Example fix
// before (dagger.json)
{ "modules": { "my-sdk": { "as-sdk": { "name": "my-sdk" } } } }
// after (dagger.json)
{ "modules": { "my-sdk": { "source": "modules/my-sdk", "pin": "abc123...", "as-sdk": { "name": "my-sdk" } } } } Defensive patterns
Strategy: validation
Validate before calling
import "encoding/json"
func sdkEntryHasSource(daggerJSONPath, sdkName string) error {
raw, err := os.ReadFile(daggerJSONPath)
if err != nil { return err }
var cfg struct {
Modules map[string]struct {
Source string `json:"source"`
} `json:"modules"`
}
if err := json.Unmarshal(raw, &cfg); err != nil { return err }
e, ok := cfg.Modules[sdkName]
if !ok { return fmt.Errorf("entry %q missing", sdkName) }
if e.Source == "" { return fmt.Errorf("entry %q has empty source", sdkName) }
return nil
} Type guard
func entryHasSource(e ModuleEntry) bool { return e.Source != "" } Try / catch
mod, entry, src, err := installedSDKSourceForModule(moduleName, entry)
if err != nil && strings.Contains(err.Error(), "has no source") {
return fmt.Errorf("reinstall %q to populate source: `dagger sdk install %s`", moduleName, moduleName)
} Prevention
- Prefer `dagger sdk install` over manual dagger.json edits so `source` (and `pin`) are always populated.
- Validate dagger.json after merges: every modules entry must have a non-empty `source`.
- Do not scaffold module entries with placeholder/empty source values; fill them before use.
- Review git diffs of dagger.json for dropped `source` fields.
When it happens
Trigger: installedSDKSource resolves a name to a workspace.ModuleEntry whose `source` field is empty or unset (and no pin can make it non-empty), e.g. a dagger.json modules entry that only contains an as-sdk block with no source path.
Common situations: Hand-editing dagger.json and adding an SDK/module entry with only a name but no `source`; tooling or a merge that dropped the source field; an entry scaffolded by a script that expected source to be filled in later; corrupt or truncated dagger.json.
Related errors
- no source
- encode workspace config: %w
- no source
- module provenance: module %q has no source
- module provenance: unexpected module source kind %q
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/aaaf93da502efafa.
Report an issue: GitHub.