python-poetry/poetry · error · ValueError

Bad script ({name}): script needs to specify a function with

Error message

Bad script ({name}): script needs to specify a function within a module like: module(.submodule):function
Instead got: {script_with_extras}

What it means

Raised by EditableBuilder._build_scripts at src/poetry/masonry/builders/editable.py:163-179 when a script entry under [tool.poetry.scripts] does not split into exactly 'module' and 'callable' on ':'. The split raising ValueError ('not enough' = no colon, 'too many' = multiple colons) is caught and re-raised with guidance. Format must be module(.submodule):function.

Source

Thrown at src/poetry/masonry/builders/editable.py:179

            script_without_extras = script_with_extras.split("[")[0]
            try:
                module, callable_ = script_without_extras.split(":")
            except ValueError as exc:
                msg = (
                    f"Bad script ({name}): script needs to specify a function within a"
                    " module like: module(.submodule):function\nInstead got:"
                    f" {script_with_extras}"
                )
                if "not enough values" in str(exc):
                    msg += (
                        "\nHint: If the script depends on module-level code, try"
                        " wrapping it in a main() function and modifying your script"
                        f' like:\n{name} = "{script_with_extras}:main"'
                    )
                elif "too many values" in str(exc):
                    msg += '\nToo many ":" found!'

                raise ValueError(msg)

            callable_holder = callable_.split(".", 1)[0]

            script_file = scripts_path.joinpath(name)
            self._debug(
                f"  - Adding the <c2>{name}</c2> script to <b>{scripts_path}</b>"
            )
            with script_file.open("w", encoding="utf-8") as f:
                f.write(
                    decode(
                        SCRIPT_TEMPLATE.format(
                            python=self._env.python,
                            module=module,
                            callable_holder=callable_holder,
                            callable_=callable_,
                        )
                    )
                )

View on GitHub (pinned to 92b74dcfe3)

Solutions

  1. Rewrite the entry as module:func, e.g. 'foo = "mypkg.cli:main"'.
  2. If the target is module-level code, wrap it in a main() function and point at ':main'.
  3. Remove extra colons; submodule dotted form goes before the single colon (mypkg.sub:func).

Example fix

# before
[tool.poetry.scripts]
foo = "mypkg"          # no :function
bar = "a:b:c"          # too many colons

# after
[tool.poetry.scripts]
foo = "mypkg:main"
bar = "a.sub:run"
Defensive patterns

Strategy: validation

Validate before calling

import re

def validate_script_entry(script: str) -> None:
    target = script.split('[')[0]
    parts = target.split(':')
    if len(parts) != 2 or not parts[0] or not parts[1]:
        raise ValueError(
            f'Bad script {script!r}; expected module(.submodule):function'
        )

Type guard

def is_valid_script(script: str) -> bool:
    target = script.split('[')[0]
    parts = target.split(':')
    return len(parts) == 2 and bool(parts[0]) and bool(parts[1])

Try / catch

try:
    builder._build_scripts(scripts)
except ValueError as e:
    if 'Bad script' in str(e):
        raise SystemExit(f'Fix [tool.poetry.scripts]: {e}') from e
    raise

Prevention

When it happens

Trigger: Running `poetry install` (editable, on the current project) when [tool.poetry.scripts] has an entry like 'foo = "mymain"' (no ':function') or 'foo = "a:b:c"' (two colons). Build during editable install of the project.

Common situations: Copy-pasted a setuptools console_scripts entry that omits the function, pointed a script at a module rather than a callable, or accidentally used a Windows drive-letter colon.

Related errors


AI-assisted analysis of python-poetry/poetry@92b74dcfe3 (2026-08-04). Data as JSON: /data/errors/cc12624da9257bd0.json. Report an issue: GitHub.