Skip to content

fix(cli): ao start --interactive crashes on flat local config#1793

Open
i-trytoohard wants to merge 1 commit intomainfrom
fix/interactive-flat-config-crash
Open

fix(cli): ao start --interactive crashes on flat local config#1793
i-trytoohard wants to merge 1 commit intomainfrom
fix/interactive-flat-config-crash

Conversation

@i-trytoohard
Copy link
Copy Markdown
Collaborator

Summary

ao start --interactive crashes with Cannot read properties of undefined when the project uses a flat (non-wrapped) local agent-orchestrator.yaml.

Root cause: The else branch (non-canonical config path) reads raw YAML and assumes rawConfig.projects[projectId] exists. Flat configs have no projects: key, so this is undefined[projectId] → crash.

Fix: Replace the raw YAML manipulation in the else branch with the same readProjectBehaviorConfig/writeProjectBehaviorConfig helpers that the if branch already uses. These helpers correctly handle both flat and wrapped config shapes via loadLocalProjectConfigDetailed.

Fixes #1791

Test

  1. Create a flat agent-orchestrator.yaml (no projects: key):
    agent: claude-code
    repo: https://github.com/example/my-repo
  2. Run ao start --interactive
  3. Select orchestrator and worker agents
  4. Before: Cannot read properties of undefined
  5. After: Agent selections saved, ao start proceeds normally

Also verify wrapped configs still work — the readProjectBehaviorConfig/writeProjectBehaviorConfig pair handles both shapes transparently.

When `ao start --interactive` saves agent selections for a non-canonical
config path, the else branch assumed `rawConfig.projects` exists. Flat
local configs have no `projects:` key, causing a crash.

Use the same readProjectBehaviorConfig/writeProjectBehaviorConfig helpers
that the if-branch already uses, which handle both flat and wrapped shapes.

Fixes #1791
@github-actions
Copy link
Copy Markdown
Contributor

Test Coverage Report

Metric Value
Lines covered 851/1227
Lines not covered 376/1227
Overall coverage 69.4%

Uncovered lines

  • packages/cli/src/commands/start.ts: L115-L116, L127-L129, L132-L134, L136, L138-L142, L145-L146, L148, L150-L154, L156-L158, L198-L199, L204-L222, L224-L231, L233-L234, L240-L246, L248, L279-L280, L294-L296, L305-L306, L309-L333, L378-L392, L394-L397, L399-L413, L441, L452, L476-L477, L480-L481, L489-L490, L497-L502, L540-L541, L565-L568, L582-L583, L590-L600, L603-L604, L628-L629, L632-L636, L644-L651, L658-L659, L696-L699, L714-L719, L736-L738, L740-L747, L749-L751, L753-L758, L760-L761, L855-L858, L905, L927-L935, L963-L971, L979-L983, L992-L994, L1027-L1028, L1044-L1045, L1051-L1052, L1054-L1055, L1059, L1114-L1115, L1133-L1138, L1171-L1172, L1178-L1179, L1250, L1270-L1271, L1355-L1356, L1408-L1425, L1482, L1516-L1518, L1541-L1552, L1579-L1587, L1598-L1599, L1633-L1634, L1642-L1653, L1656, L1672, L1678, L1681-L1689, L1699-L1700, L1741-L1744, L1747, L1749-L1751, L1756-L1757, L1766-L1770, L1772-L1773, L1782-L1783, L1793-L1798, L1834-L1840

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 10, 2026

Greptile Summary

This PR fixes a crash in ao start --interactive when the local config is a flat (non-wrapped) YAML file with no projects: key. The old else branch read the raw YAML and blindly indexed rawConfig.projects[projectId], which was undefined for flat configs. The fix replaces the raw YAML manipulation with the same readProjectBehaviorConfig/writeProjectBehaviorConfig helpers already used by the if branch.

  • The crash path is correctly removed — both flat and wrapped local configs are now handled via the shared helpers.
  • After the fix, the if and else branches have become byte-for-byte identical, leaving dead branching that can be simplified.

Confidence Score: 4/5

Safe to merge — the crash fix is correct and non-destructive; the only remaining issue is cosmetic dead branching.

The fix correctly eliminates the undefined-access crash by delegating to helpers that already handle all config shapes. The only leftover issue is that the if/else condition is now vacuous — both branches do exactly the same thing — which is a code quality concern but does not affect runtime correctness.

packages/cli/src/commands/start.ts — the duplicate if/else block around lines 1528-1552 is worth collapsing.

Important Files Changed

Filename Overview
packages/cli/src/commands/start.ts Crash fix for flat local config in --interactive mode; the if/else branches are now duplicate and can be collapsed to a single code path.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["ao start --interactive"] --> B["promptAgentSelection()"]
    B --> C{agentOverride?}
    C -- No --> G["runStartup()"]
    C -- Yes --> D["readProjectBehaviorConfig(project.path)"]
    D --> E["Set orchestrator.agent + worker.agent"]
    E --> F["writeProjectBehaviorConfig(project.path, nextLocalConfig)"]
    F --> G
Loading

Comments Outside Diff (1)

  1. packages/cli/src/commands/start.ts, line 1528-1552 (link)

    P2 After this fix, both branches of the if/else are byte-for-byte identical — isCanonicalGlobalConfigPath no longer produces any difference in behaviour. The entire conditional can be collapsed into a single code path, removing the dead branch.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: packages/cli/src/commands/start.ts
    Line: 1528-1552
    
    Comment:
    After this fix, both branches of the `if`/`else` are byte-for-byte identical — `isCanonicalGlobalConfigPath` no longer produces any difference in behaviour. The entire conditional can be collapsed into a single code path, removing the dead branch.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/cli/src/commands/start.ts:1528-1552
After this fix, both branches of the `if`/`else` are byte-for-byte identical — `isCanonicalGlobalConfigPath` no longer produces any difference in behaviour. The entire conditional can be collapsed into a single code path, removing the dead branch.

```suggestion
            const nextLocalConfig = readProjectBehaviorConfig(project.path);
            nextLocalConfig.orchestrator = {
              ...(nextLocalConfig.orchestrator ?? {}),
              agent: orchestratorAgent,
            };
            nextLocalConfig.worker = {
              ...(nextLocalConfig.worker ?? {}),
              agent: workerAgent,
            };
            writeProjectBehaviorConfig(project.path, nextLocalConfig);
            console.log(chalk.dim(`  ✓ Saved to ${project.path}/agent-orchestrator.yaml\n`));
```

Reviews (1): Last reviewed commit: "fix(cli): use behavior config helpers fo..." | Re-trigger Greptile

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.

fix(cli): ao start --interactive crashes on flat local config

1 participant