bmad-code-org/BMAD-METHOD · error · Error
version is not available when nothing is installed
Error message
version is not available when nothing is installed
What it means
Thrown by the ExistingInstall.version getter when the installation snapshot reports installed=false. ExistingInstall.empty() (returned when no bmad dir or no core/modules/manifest are detected) always sets installed=false, so reading .version on it is undefined. The getter exists to fail fast rather than return null silently.
Source
Thrown at tools/installer/core/existing-install.js:25
* Immutable snapshot of an existing BMAD installation.
* Pure query object — no filesystem operations after construction.
*/
class ExistingInstall {
#version;
constructor({ installed, version, hasCore, modules, ides }) {
this.installed = installed;
this.#version = version;
this.hasCore = hasCore;
this.modules = Object.freeze(modules.map((m) => Object.freeze({ ...m })));
this.moduleIds = Object.freeze(this.modules.map((m) => m.id));
this.ides = Object.freeze([...ides]);
Object.freeze(this);
}
get version() {
if (!this.installed) {
throw new Error('version is not available when nothing is installed');
}
return this.#version;
}
static empty() {
return new ExistingInstall({
installed: false,
version: null,
hasCore: false,
modules: [],
ides: [],
});
}
/**
* Scan a bmad directory and return an immutable snapshot of what's installed.
* @param {string} bmadDir - Path to bmad directory
* @returns {Promise<ExistingInstall>}View on GitHub (pinned to b70486b9bd)
Solutions
- Check `existingInstall.installed` before reading `existingInstall.version` (mirror uninstall.js:65).
- If you need a display string, use `existingInstall.installed ? existingInstall.version : 'unknown'`.
- Ensure the directory passed to detect() actually contains a _bmad/ folder.
Example fix
// before const install = await ExistingInstall.detect(bmadDir); console.log(install.version); // after const install = await ExistingInstall.detect(bmadDir); console.log(install.installed ? install.version : 'unknown');
Defensive patterns
Strategy: type-guard
Validate before calling
const install = await ExistingInstall.detect(bmadDir);
if (!install.installed) {
// handle no-install case without reading .version
return;
} Type guard
function hasVersion(install) {
return install instanceof ExistingInstall && install.installed === true;
} Prevention
- Always branch on `existingInstall.installed` before reading `.version`.
- Treat ExistingInstall.empty() as 'no install' and skip version-dependent logic.
- Mirror the guard pattern used in commands/uninstall.js.
When it happens
Trigger: Calling `existingInstall.version` on an instance produced by `ExistingInstall.empty()`, or on any ExistingInstall where `detect()` found no core directory, no modules, and no manifest.yaml. Happens in code paths that skip the `existingInstall.installed` guard before reading version.
Common situations: Running uninstall/status/update commands against a directory that never had BMAD installed, or where _bmad/ was deleted by hand. A caller that assumes `.version` is always populated after `detect()`.
Related errors
- BMAD not installed at ${bmadDir}. Use regular install for fi
- ${label} does not exist: ${dirPath}
- ${label} is not a directory: ${dirPath}
- ${label} is not readable: ${dirPath}
- ${label} does not exist: ${filePath}
AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13).
Data as JSON: /api/errors/434a714ef020f186.
Report an issue: GitHub.