crewAIInc/crewAI · warning · SystemExit

Failed to publish tool. Local changes need to be resolved be

Error message

Failed to publish tool.
Local changes need to be resolved before publishing. Please do the following:
* Commit your changes.
* Push to sync with the remote.
* Pull the latest changes from the remote.

Once your repository is up-to-date, retry publishing the tool.

What it means

Raised (SystemExit with no code, i.e. exit 0) by ToolCommand.publish() in crewai_cli/tools/main.py when git.Repository().is_synced() returns False and --force was not passed. Publishing packages the current project as a tool; the CLI requires a clean, committed, pushed and up-to-date git state so the published artifact is traceable to a commit.

Source

Thrown at lib/cli/src/crewai_cli/tools/main.py:115

            self.login()
            subprocess.run(["git", "init"], check=True)  # noqa: S607
            console.print(
                f"[green]Created custom tool [bold]{folder_name}[/bold]. Run [bold]cd {project_root}[/bold] to start working.[/green]"
            )
        finally:
            os.chdir(old_directory)

    def publish(self, is_public: bool, force: bool = False) -> None:
        if not git.Repository().is_synced() and not force:
            console.print(
                "[bold red]Failed to publish tool.[/bold red]\n"
                "Local changes need to be resolved before publishing. Please do the following:\n"
                "* [bold]Commit[/bold] your changes.\n"
                "* [bold]Push[/bold] to sync with the remote.\n"
                "* [bold]Pull[/bold] the latest changes from the remote.\n"
                "\nOnce your repository is up-to-date, retry publishing the tool."
            )
            raise SystemExit()

        project_name = get_project_name(require=True)
        assert isinstance(project_name, str)  # noqa: S101

        project_version = get_project_version(require=True)
        assert isinstance(project_version, str)  # noqa: S101

        project_description = get_project_description(require=False)
        encoded_tarball = None

        console.print("[bold blue]Discovering tools from your project...[/bold blue]")
        project_utils = _require_project_utils()
        available_exports = project_utils.extract_available_exports()

        if available_exports:
            console.print(
                f"[green]Found these tools to publish: {', '.join([e['name'] for e in available_exports])}[/green]"
            )

View on GitHub (pinned to 754d7323be)

Solutions

  1. Commit all local changes: `git add -A && git commit -m "..."`.
  2. Push and synchronize: `git push` then `git pull` so is_synced() passes.
  3. If the repo state is intentionally dirty (e.g. CI), pass --force: `crewai tool publish --force`.
  4. Ensure a remote origin is configured (`git remote -v`) — no remote means never synced.

Example fix

# before
crewai tool publish --public  # uncommitted changes -> SystemExit

# after
git add -A && git commit -m "chore: publish tool v0.1.1" && git push
git pull
grewai tool publish --public  # typo guard: crewai tool publish --public
Defensive patterns

Strategy: validation

Validate before calling

import subprocess
def git_is_synced() -> bool:
    def clean(cmd):
        return subprocess.run(cmd, capture_output=True, text=True).stdout.strip() == ""
    return (
        clean(["git", "status", "--porcelain"])
        and clean(["git", "log", "@{u}..", "--oneline"])
        and clean(["git", "log", "..@{u}", "--oneline"])
    )

Prevention

When it happens

Trigger: Running `crewai tool publish` with uncommitted changes, commits not pushed to the remote, local branch behind the remote (unpulled changes), or no remote configured — and without the --force flag.

Common situations: Developer edits pyproject.toml or tool code and publishes without committing; CI publish job running on a checkout that never pushes; detached HEAD or freshly cloned repo that is ahead of origin.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/845176866f3819b6. Report an issue: GitHub.