Skip to content

fix(init): reject empty/whitespace project names#2200

Open
nadav-y wants to merge 2 commits into
microsoft:mainfrom
nadav-y:fix/init-empty-project-name
Open

fix(init): reject empty/whitespace project names#2200
nadav-y wants to merge 2 commits into
microsoft:mainfrom
nadav-y:fix/init-empty-project-name

Conversation

@nadav-y

@nadav-y nadav-y commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

apm.yml can end up with an empty name field (name: ''), written by
apm itself rather than by a user typo. Once that happens, every later
apm install / apm lock / apm compile on that manifest hard-fails
with:

Failed to parse apm.yml: Invalid apm.yml identity: 'name' must be a non-empty string

with no way to recover short of hand-editing the file.

Root cause

#2155 tightened APMPackage.from_apm_yml's identity validation: name
and version must now be non-empty strings, not just present keys. That
check itself is correct and intentional. What's missing is upstream of
it: nothing guaranteed a valid name before apm.yml was written to
disk in the first place, so two pre-existing, unrelated code paths could
silently produce name: '':

  1. apm install <pkg> auto-bootstrap (commands/install.py) — when no
    apm.yml exists, the project name is derived from Path.cwd().name
    (or Path.home().name for -g/global installs). That's '' at a
    filesystem/drive root. Concretely: a container image with no WORKDIR
    set (Docker's default WORKDIR is /) running
    apm install <pkg> --target claude writes name: '' straight into the
    auto-created apm.yml. This is the confirmed trigger for the reported
    bug
    — verified end-to-end by reproducing an empty Path.cwd().name.

  2. apm init interactive promptrich.Prompt.ask() only substitutes
    the default when the raw input is exactly "". Typing a single space
    at the "Project name" prompt returns " " (not the default), which the
    caller then .strip()s to "" before validation. The old
    _validate_project_name only rejected path separators and '..', not
    emptiness, so this also silently wrote name: ''. Separately verified
    and reproduced; not what caused the reported issue, but the same class
    of bug through a different entry point.

Fix

  • _validate_project_name now rejects empty/whitespace-only names (in
    addition to the existing path-separator/'..' checks).
  • New _resolve_bootstrap_project_name() helper, used by the install.py
    auto-bootstrap path, falls back to "my-project" (matching the existing
    placeholder convention in commands/deps/cli.py) when the derived
    candidate is invalid.
  • Updated the apm init interactive-prompt and CLI-arg error messages to
    mention emptiness, not just path separators.

Test plan

  • tests/unit/test_init_command.py: new unit tests for
    _validate_project_name (empty/whitespace) and
    _resolve_bootstrap_project_name (fallback + passthrough), plus an
    integration test that a blank/whitespace apm init prompt re-prompts
    instead of writing name: ''.
  • Manually reproduced both trigger paths against an unpatched checkout
    and confirmed the fix resolves both.
  • ruff check / ruff format --check clean on all touched files.
  • Full test_init_command.py + test_install_command.py suites pass
    (174 tests).

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings July 14, 2026 09:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens project-name handling so apm init and the apm install <pkg> auto-bootstrap path no longer create apm.yml manifests with an empty/whitespace name, aligning upstream behavior with the stricter identity validation introduced in #2155.

Changes:

  • Reject empty/whitespace project names in _validate_project_name.
  • Add _resolve_bootstrap_project_name() and use it in install auto-bootstrap to fall back to "my-project" when Path.cwd().name (or Path.home().name) is empty/invalid.
  • Update apm init error messages and add unit/integration tests covering the new validation and interactive re-prompt behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
tests/unit/test_init_command.py Adds unit tests for empty/whitespace name validation and bootstrap-name fallback, plus an interactive re-prompt regression test.
src/apm_cli/commands/install.py Routes auto-bootstrap project naming through _resolve_bootstrap_project_name() before writing apm.yml.
src/apm_cli/commands/init.py Updates CLI + interactive error messages to mention non-empty requirement.
src/apm_cli/commands/_helpers.py Extends _validate_project_name to reject empty/whitespace; introduces _resolve_bootstrap_project_name().

Comment thread src/apm_cli/commands/init.py
_validate_project_name only checked for path separators and '..', so an
empty or whitespace-only name (e.g. `apm install <pkg>` auto-bootstrapping
apm.yml from Path.cwd().name at a container's unset root WORKDIR, or a
blank `apm init` prompt) silently wrote `name: ''` into apm.yml. Every
later install/lock/compile then failed with "Invalid apm.yml identity:
'name' must be a non-empty string" once microsoft#2155 tightened
APMPackage.from_apm_yml's identity check.

Reject empty/whitespace names in _validate_project_name, and add
_resolve_bootstrap_project_name() so the install auto-bootstrap path
falls back to "my-project" instead of writing an empty name.

`apm init` had the same gap: when no project_name arg is given, the
early _validate_project_name check (guarded by `if project_name and
...`) is skipped entirely, so with --yes the cwd-derived name flowed
straight into _get_default_config unvalidated -- silently writing
'name: ""' at a filesystem/drive root. Route it through
_resolve_bootstrap_project_name too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@nadav-y nadav-y force-pushed the fix/init-empty-project-name branch from 9e77d13 to 4c30553 Compare July 14, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants