gemini-cli - ✅(Solved) Fix A2A server shallow-merges user and workspace settings, causing nested config to be lost [1 pull requests, 3 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
google-gemini/gemini-cli#25747Fetched 2026-04-22 08:03:37
View on GitHub
Comments
3
Participants
2
Timeline
11
Reactions
0
Timeline (top)
commented ×3mentioned ×3subscribed ×3cross-referenced ×1

The A2A server currently combines user settings and workspace settings with a shallow object spread in packages/a2a-server/src/config/settings.ts. That means any nested object defined in workspace settings replaces the entire corresponding object from user settings, instead of overriding only the specific keys the workspace intended to change.

This can silently drop valid user configuration.

Root Cause

That results in unexpected behavior for end users because repo-level settings should usually override specific fields, not erase unrelated defaults they set globally.

Fix Action

Fix / Workaround

Proposed changes

  1. Change the A2A server settings merge logic in packages/a2a-server/src/config/settings.ts so nested settings objects are merged instead of replaced wholesale.
  2. Preserve current precedence rules: workspace settings should still override user settings, but only for explicitly provided nested keys.
  3. Add or update tests in packages/a2a-server/src/config/settings.test.ts to verify that:
    • fileFiltering merges correctly
    • partial workspace overrides do not erase unrelated user keys
    • similar nested sections such as tools, telemetry, and experimental behave correctly if applicable
  4. Update the existing shallow-merge test so it reflects the intended merged behavior rather than the current replacement behavior.
  5. If there is existing shared merge logic in the main CLI that can be reused safely, prefer reusing that approach rather than inventing a second merge strategy.

PR fix notes

PR #25770: fix(a2a): implement deep merge for settings (#25747)

Description (problem / solution / changelog)

Fixes #25747

The A2A server previously used a shallow spread to merge user and workspace configurations, causing nested objects (e.g. fileFiltering, tools) to be overwritten.

This change replaces the shallow merge with an immutable deep merge so that workspace settings override only explicitly defined keys while preserving other user-defined values.

Architecture note: The CLI deep merge logic was not reused directly due to package boundaries (A2A does not depend on CLI), so a minimal local recursive implementation was added following the same behavior.

Key changes:

  • Replaced shallow object spread with deep merge
  • Preserved nested user configuration keys
  • Ensured workspace overrides apply per-key
  • Added prototype pollution safeguards
  • Updated tests to validate nested merge behavior

Changed files

  • packages/a2a-server/src/config/settings.test.ts (modified, +32/-3)
  • packages/a2a-server/src/config/settings.ts (modified, +67/-6)

Code Example

return {
  ...userSettings,
  ...workspaceSettings,
};

---

{
  "fileFiltering": {
    "respectGitIgnore": true,
    "enableRecursiveFileSearch": true
  }
}

---

{
  "fileFiltering": {
    "respectGitIgnore": false
  }
}

---

{
  "fileFiltering": {
    "respectGitIgnore": false,
    "enableRecursiveFileSearch": true
  }
}

---

{
  "fileFiltering": {
    "respectGitIgnore": false
  }
}
RAW_BUFFERClick to expand / collapse

Summary

The A2A server currently combines user settings and workspace settings with a shallow object spread in packages/a2a-server/src/config/settings.ts. That means any nested object defined in workspace settings replaces the entire corresponding object from user settings, instead of overriding only the specific keys the workspace intended to change.

This can silently drop valid user configuration.

Why this is a bug

The A2A server settings structure includes nested sections such as:

  • tools
  • telemetry
  • fileFiltering
  • experimental

Right now, settings are merged like this in effect:

return {
  ...userSettings,
  ...workspaceSettings,
};

That is a shallow merge, as in if both user and workspace settings define the same top-level object, the workspace version replaces the whole object. Any keys present only in the user settings disappear.

That results in unexpected behavior for end users because repo-level settings should usually override specific fields, not erase unrelated defaults they set globally.

Concrete example

User settings:

{
  "fileFiltering": {
    "respectGitIgnore": true,
    "enableRecursiveFileSearch": true
  }
}

Workspace settings:

{
  "fileFiltering": {
    "respectGitIgnore": false
  }
}

Expected merged result:

{
  "fileFiltering": {
    "respectGitIgnore": false,
    "enableRecursiveFileSearch": true
  }
}

Current actual result:

{
  "fileFiltering": {
    "respectGitIgnore": false
  }
}

The user's enableRecursiveFileSearch setting is silently lost.

Evidence in the codebase

The shallow merge happens in:

There is already a TODO indicating the settings handling is incomplete:

The current test suite also encodes the shallow behavior:

That test currently expects nested values like enableRecursiveFileSearch to become undefined, which reflects the bug rather than the desired behavior.

For comparison, the main CLI already uses deep merge logic for settings:

Proposed changes

  1. Change the A2A server settings merge logic in packages/a2a-server/src/config/settings.ts so nested settings objects are merged instead of replaced wholesale.
  2. Preserve current precedence rules: workspace settings should still override user settings, but only for explicitly provided nested keys.
  3. Add or update tests in packages/a2a-server/src/config/settings.test.ts to verify that:
    • fileFiltering merges correctly
    • partial workspace overrides do not erase unrelated user keys
    • similar nested sections such as tools, telemetry, and experimental behave correctly if applicable
  4. Update the existing shallow-merge test so it reflects the intended merged behavior rather than the current replacement behavior.
  5. If there is existing shared merge logic in the main CLI that can be reused safely, prefer reusing that approach rather than inventing a second merge strategy.

Expected outcome

After the fix, users should be able to define global defaults in user settings and have workspace settings override only the specific nested values they need, without silently losing unrelated configuration.

Possible acceptance criteria

[] User and workspace settings merge correctly for nested objects [] Partial workspace overrides preserve unspecified user values [] Test coverage exists for at least one nested settings object, ideally fileFiltering [] No regressions in existing A2A settings loading behavior outside the merge semantics

extent analysis

TL;DR

Change the A2A server settings merge logic to use a deep merge instead of a shallow merge to preserve nested user settings.

Guidance

  • Update the merge logic in packages/a2a-server/src/config/settings.ts:128 to use a deep merge, ensuring that nested settings objects are merged instead of replaced.
  • Review the existing test suite in packages/a2a-server/src/config/settings.test.ts:127 and update tests to verify the correct merge behavior for nested settings objects.
  • Consider reusing the merge logic from the main CLI in packages/cli/src/config/settings.ts:257 to maintain consistency across the application.
  • Verify that the updated merge logic preserves the current precedence rules, where workspace settings override user settings only for explicitly provided nested keys.

Example

// Example of a deep merge function
function deepMerge(target, source) {
  if (typeof target === 'object' && typeof source === 'object') {
    for (const key in source) {
      if (typeof source[key] === 'object') {
        if (!target[key]) {
          target[key] = {};
        }
        deepMerge(target[key], source[key]);
      } else {
        target[key] = source[key];
      }
    }
  }
  return target;
}

// Usage
const userSettings = {
  fileFiltering: {
    respectGitIgnore: true,
    enableRecursiveFileSearch: true
  }
};

const workspaceSettings = {
  fileFiltering: {
    respectGitIgnore: false
  }
};

const mergedSettings = deepMerge({}, userSettings);
deepMerge(mergedSettings, workspaceSettings);

console.log(mergedSettings);
// Output:
// {
//   fileFiltering: {
//     respectGitIgnore: false,
//     enableRecursiveFileSearch: true
//   }
// }

Notes

The proposed changes should be thoroughly tested to ensure that the updated merge logic does not introduce any regressions in the existing A2A settings loading behavior.

Recommendation

Apply the proposed changes to update the A2A server settings merge logic to use a deep merge, ensuring that nested user settings are preserved. This change will allow users to define global defaults in user settings and have workspace settings override only the specific nested values they need, without silently losing unrelated configuration.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

gemini-cli - ✅(Solved) Fix A2A server shallow-merges user and workspace settings, causing nested config to be lost [1 pull requests, 3 comments, 2 participants]