github/spec-kit · error · IntegrationDescriptorError
Script entry must be a non-empty string
Error message
Script entry must be a non-empty string
What it means
Raised by IntegrationDescriptor._validate() (src/specify_cli/integrations/catalog.py:809) when an element of provides.scripts is not a string or is empty/whitespace-only. Unlike command entries (mappings), script entries are plain relative-path strings, and each must be non-empty before the path-safety check runs.
Source
Thrown at src/specify_cli/integrations/catalog.py:809
"Command entry missing 'name' or 'file'"
)
cmd_name = cmd["name"]
cmd_file = cmd["file"]
if not isinstance(cmd_name, str) or not cmd_name.strip():
raise IntegrationDescriptorError(
"Command entry 'name' must be a non-empty string"
)
if not isinstance(cmd_file, str) or not cmd_file.strip():
raise IntegrationDescriptorError(
"Command entry 'file' must be a non-empty string"
)
if os.path.isabs(cmd_file) or ".." in Path(cmd_file).parts or Path(cmd_file).drive or Path(cmd_file).anchor:
raise IntegrationDescriptorError(
f"Command entry 'file' must be a relative path without '..': {cmd_file}"
)
for script_entry in scripts:
if not isinstance(script_entry, str) or not script_entry.strip():
raise IntegrationDescriptorError(
"Script entry must be a non-empty string"
)
if os.path.isabs(script_entry) or ".." in Path(script_entry).parts or Path(script_entry).drive or Path(script_entry).anchor:
raise IntegrationDescriptorError(
f"Script entry must be a relative path without '..': {script_entry}"
)
# -- Property accessors -----------------------------------------------
@property
def id(self) -> str:
return self.data["integration"]["id"]
@property
def name(self) -> str:
return self.data["integration"]["name"]
@propertyView on GitHub (pinned to bf88c9f9a8)
Solutions
- Make every provides.scripts element a non-empty string path.
- Remove null/empty placeholders from the list.
- Move any command mappings (name/file) into provides.commands instead.
- Re-validate the descriptor.
Example fix
# before
provides:
scripts:
- {name: setup, file: setup.sh}
# after
provides:
scripts:
- scripts/bash/setup.sh Defensive patterns
Strategy: type-guard
Validate before calling
def bad_script_entries(scripts):
return [s for s in scripts if not isinstance(s, str) or not s.strip()] Type guard
def is_script_entry(v) -> bool:
return isinstance(v, str) and bool(v.strip()) Prevention
- Scripts are plain strings, not mappings — put name/file entries in commands.
- Remove empty or null list items.
- Validate the whole provides block with a helper before loading.
When it happens
Trigger: A descriptor with 'provides: scripts: [null, setup.sh, ""]' or a script entry parsed as a number/mapping; the isinstance/strip check in the for-loop over scripts raises.
Common situations: Mixing command-style mappings into the scripts list; YAML list entries that are empty lines or placeholder nulls; converting a map of script names to paths without unwrapping.
Related errors
- Invalid provides.commands: expected a list
- Invalid provides.scripts: expected a list
- Integration must provide at least one command or script
- Each command entry must be a mapping
- Command entry missing 'name' or 'file'
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/17cdda16abb3f650.
Report an issue: GitHub.