Skip to content

store_memory fails for entire session and all MCP servers are stripped - shared root cause: managedSettings fails closed on serverFetchFailed flap #4602

Description

@tabriggs

Relationship to existing issues — please read before triaging as duplicate

This is the same underlying mechanism as several open issues, reached through a different trigger, and it surfaces a second symptom nobody has reported yet (store_memory).

Issue What it reports How this differs
#4419 Interim fail-closed installs an empty allow list [[]]; servers registering in that window are dropped permanently. Repros with source=none, serverFetchFailed=false, no managed policy at all — a purely pre-emptive deny Here a managed policy IS in force (source=mdm, remoteControl.mode=requireSSO) and the deny is driven by serverFetchFailed oscillating false→true→false→true with no token available to fetch server policy. Different code path into the same deny
#4512 Asks that locally-defined stdio MCP servers still run when the registry policy fetch fails and no managed policy is in force Same ask, but with a managed policy present — so the "no policy in force" carve-out would not cover this case
#4349 Policy fetch fails closed on a valid enum value, blocking all local/custom MCP servers Same fail-closed outcome, different input (token acquisition failure rather than enum parsing)
#4535 store_memory fails in 1.0.81 prereleases with Instance id is required Same version line, different error: session settings are unavailable. May share a root cause
#1751 (closed) store_memory consistently fails with "Unable to store memory" Same user-visible symptom, resurfaced

The new information in this report:

  1. store_memory and the MCP allow-list strip are the same defect. No existing issue connects them. Both consume session settings mid-flap and both fail closed, 918 ms apart in the same startup sequence.
  2. They differ in recovery, which localises the memory bug precisely. The MCP host re-evaluates settings and can recover mid-session; native memory tool preparation is a one-shot init with no retry and stays dead for the session's full duration. That asymmetry is the actionable finding.
  3. Reproduces with a managed policy present, via token-acquisition failure rather than the empty-interim-list window.
  4. Not window-scoped. 11/11 sessions across 2 days and 2 host versions, including a deliberate post-restart session.
  5. Machine-generated evidence across every session on both days (section 11 of the attached report).

If maintainers prefer, this can be folded into #4419 as an additional trigger — but the store_memory correlation and the missing-retry finding should survive the merge.


Version and basics (answering the usual first questions up front)

Question Answer
Copilot CLI version 1.0.81-5
OS Windows (Windows_NT), x64
Model Claude Opus 5 (claude-opus-5)
Host wrapper Agency 2026.8.24.6 (commit 290b8f85), x86_64-windows
Also reproduced on Agency 2026.8.21.9 (commit b9d0abc7) — host upgrade did not fix it
Is it reproducible? Yes — 100%. 11/11 store_memory failures across 4 sessions; allow-list skips in 11/11 sessions over 2 days
Does restarting fix it? No. A deliberate post-restart session shows 242 allow-list skips and 116 no token events
Does reinstalling/upgrading fix it? No. Persisted across two Agency host versions
Is it a config problem? No. ~/.copilot/mcp-config.json is valid JSON, no BOM, last modified a month prior. The strip also hits auto-injected and builtin servers that are not in it
Is it the MCP servers themselves? No. The Microsoft MCP Platform team investigated and ruled out the server side (quoted below)
Is there a workaround? None found. Degraded fallbacks only (Azure CLI for ADO, Outlook COM for mail)
Regression? Unclear. A previously closed issue (#1751) describes the same user-visible symptom
Related issues #4535 (same 1.0.81 line, different error string), #1751 (closed, same symptom)
Managed settings HKLM\SOFTWARE\Policies\GitHubCopilotremoteControl.mode=requireSSO; managed-settings.json does not exist ([MDM] No managed settings found)
Feature flags copilot_cli_mcp_allowlist=true, copilot_cli_mcp_enterprise_allowlist=true, MSFT_AGENCY=true, enable_memory_voting=true

One-line repro: on a Windows machine under MDM policy remoteControl.mode=requireSSO with no managed-settings.json, start a session — managedSettings fails to get a token, fails closed, and both the MCP allow-list check and native memory tool preparation fail with it.

Single most useful diagnostic command (run against a session log dir):

Select-String -Path "$sessionDir\process-*.log" -Pattern 'Skipping MCP server|Failed to prepare native memory tools|no token available to fetch server policy'

Summary

A single failure in the managedSettings subsystem at session startup causes two silent, high-impact defects that share one root cause:

  1. store_memory fails on every call for the entire session — while memory retrieval keeps working and the tool stays advertised to the model.
  2. Every MCP server is stripped from the session — including auto-injected and builtin ones — after they have already started and successfully authenticated.

Both consume session settings while serverFetchFailed is oscillating, and both fail closed.

Status: reproducible and persistent. 11 / 11 store_memory failures across 4 independent sessions, 2 host versions, 2+ days. A full terminal restart does not clear it.

Related: #4535 (same 1.0.81 line, different error string — Instance id is required vs session settings are unavailable), and #1751 (previously closed, same user-visible symptom).

Environment

Field Value
Copilot CLI 1.0.81-5
Host wrapper Agency 2026.8.24.6 (290b8f85), x86_64-windows — also reproduced on 2026.8.21.9 (b9d0abc7)
OS Windows (Windows_NT)
Model Claude Opus 5 (claude-opus-5)
Context tier long_context
Feature flags MSFT_AGENCY: true, enable_memory_voting: true
managed-settings.json does not exist (logged as [MDM] No managed settings found)
MDM policy source HKLM\SOFTWARE\Policies\GitHubCopilotremoteControl.mode=requireSSO

Root cause

The managedSettings subsystem cannot obtain a token to fetch server policy and fails closed. serverFetchFailed then flaps false → true → false → true during startup:

2026-08-25T18:04:05.899Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=false
2026-08-25T18:04:06.277Z [managedSettings] no token available to fetch server policy — failing closed (bypass stays disabled until policy is known)
2026-08-25T18:04:06.277Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=true
2026-08-25T18:04:06.672Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=false
2026-08-25T18:04:07.032Z [managedSettings] no token available to fetch server policy — failing closed (bypass stays disabled until policy is known)
2026-08-25T18:04:07.032Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=true

Two independent consumers read this value mid-flap and both fail closed:

  • copilot_runtime::shared_api::tools → native memory tools
  • copilot_runtime::session::mcp::agent_host → MCP allow-list evaluation

Defect 1 — store_memory fails silently for the whole session

Startup warning, emitted exactly once, with no retry and no user-visible surfacing:

[WARNING] [rust:copilot_runtime::shared_api::tools]
Failed to prepare native memory tools {"error":"GenericFailure, session settings are unavailable"}

Every subsequent call returns:

Unable to store memory: an unexpected error occurred.

The critical asymmetry:

  • Memory reports itself enabled — Memory enablement check: enabled (19 occurrences across sessions)
  • Memory retrieval worksmemory_retrieval telemetry succeeds with memories_count: 1
  • store_memory stays registered and is offered to the model every single turn:
    line 7846:       "store_memory:27193c2e",
    line 8161:       "store_memory:27193c2e",
    line 8464:       "store_memory:27193c2e",
    
  • ...but every write is dropped.

So the agent is told memory is available, calls store_memory in good faith, tells the user "I'll remember that", and the write silently disappears.

No telemetry is emitted for the failure. Searching both session logs:

Select-String '"kind": "(memory[^"]*)"'   →  memory_usage (3), memory_retrieval (2), memory_exp_assignment_check (2)
Select-String '"kind":.*(store|write)'    →  0 matches
Select-String 'Unable to store memory'    →  0 matches

There is no memory_write event, and the user-facing error string appears nowhere in the runtime logs — it is generated at the tool boundary. These failures are invisible to service-side dashboards.

Defect 2 — all MCP servers stripped by the enterprise managed allow list

918 ms before the memory failure, the same condition causes every MCP server to be discarded:

2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "ado": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "teams": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "lynx": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "charter": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "mail": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:05:06.119Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "computer-use": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:05:06.119Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "workiq": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:05:06.119Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "bluebird": not permitted by enterprise managed allow list {"agent":""}

Three things make this clearly a defect rather than a genuine policy denial:

  1. The servers had already started and authenticated successfully — Entra token acquired, initialize + notifications/initialized returned HTTP 202 — before being discarded.
  2. It hits builtin and auto-injected servers too, not just user-configured ones. bluebird and workiq are auto-injected by the host; computer-use is builtin.
  3. It is non-deterministic. The same servers load normally later with no configuration change. In one session they recovered inside the same live session 2h15m after being refused, with no restart.

Per-session skip counts on 2026-08-25:

session_20260825_103540_28160  |  allowlist-skips=29  memtool-fail=1  no-token=4
session_20260825_103630_40448  |  allowlist-skips=29  memtool-fail=1  no-token=4
session_20260825_103633_48160  |  allowlist-skips=31  memtool-fail=7  no-token=10
session_20260825_110352_9484   |  allowlist-skips=29  memtool-fail=1  no-token=4   <-- AFTER A FULL RESTART

Restarting the terminal does not clear it.

Divergent recovery — the key diagnostic clue

The two defects share a trigger but differ in recovery: the MCP host re-evaluates settings mid-session and recovers; memory tool preparation never does. Memory is a one-shot init with no retry, so it stays dead for the session's full duration.

This is what makes a retry the highest-value fix — the runtime already re-resolves these settings successfully for the MCP host.

Reproduction

  1. Run Copilot CLI 1.0.81-5 on Windows under MDM policy where remoteControl.mode=requireSSO and no managed-settings.json is present.
  2. Observe no token available to fetch server policy — failing closed in process-*.log at startup.
  3. Call store_memory with any valid payload → Unable to store memory: an unexpected error occurred.
  4. Observe configured MCP servers absent from the tool list, with not permitted by enterprise managed allow list in the same log.

No special input is required — this failed with both short and long fact values, valid scope: "user", and all required fields populated.

Impact

  1. Silent data loss. Every fact the agent is instructed to persist is discarded. Cross-session conventions never survive.
  2. Misleading agent behavior. The agent has no signal writes are broken, so it confidently tells users it will remember things it won't.
  3. Entire workflows blocked. The MCP strip disabled a production compliance-outreach workflow (Regulated Industry Minimum Bar) three days running — it depends on mail, teams, ado, and workiq.
  4. Unactionable error text. "an unexpected error occurred" gives users nothing; the real cause is only recoverable by grepping runtime logs.
  5. Invisible service-side. No failure telemetry is emitted for either defect.

Requested actions

  1. Retry instead of failing once. Have native memory tool preparation subscribe to the same settings-resolution event the MCP host already uses, rather than failing once at startup and staying dead. (Highest value — the runtime demonstrably re-resolves these settings successfully mid-session.)
  2. Fix the underlying race so session settings are reliably resolved before either shared_api::tools or session::mcp::agent_host consumes them, and investigate the serverFetchFailed oscillation.
  3. Don't advertise a broken tool. If preparation fails, either withhold store_memory or have it return an explicit memory unavailable this session so the agent can warn the user on the first failure.
  4. Surface the real cause — propagate session settings are unavailable into the tool result instead of "an unexpected error occurred".
  5. Add write telemetry — emit a memory_write success/failure event so this is observable.
  6. Don't fail closed on allow-list evaluation when policy is merely undetermined — a server that authenticated successfully shouldn't be silently discarded because a policy fetch had no token.

Note for triagers — a red herring to avoid

A parallel investigation initially blamed HTTP 429 rate-limiting on the upstream MCP gateway:

Upstream returned transient status; will retry attempt=1..4 status=429 method=tools/list

Those events are real (372 across 5 days) but are not the cause — the session whose tools actually vanished logged zero 429s and its proxy log ends on a successful exchange. The decisive string is not permitted by enterprise managed allow list in process-*.log, not anything in the MCP proxy logs.

The Microsoft MCP Platform team independently ruled out the server side:

"Looks like the store_memory tool seems to be the cause of these issues, this is not originating from our mcp servers" — Pardhu Vavila, MCP Platform Dev, 2026-08-25

Full evidence report

Attached as GHCP-CLI-store_memory-failure-report.md and reproduced inline below for searchability.
Includes per-session log line references, full managedSettings oscillation traces, telemetry-absence
verification, a machine-generated table covering all 11 sessions across both days, and two documented
red herrings.

Raw logs are not attached because they contain full session transcripts; they can be supplied to GitHub
staff privately on request (paths in section 11.6).

GHCP-CLI-store_memory-failure-report.md (click to expand)

GitHub Copilot CLI — store_memory Tool Failure Report

Filed by: @tabriggs_microsoft
Date observed: 2026-08-24
Severity: Medium — silent data loss. Memory writes fail while the feature reports itself as enabled and memory reads succeed.
(See §9.1: the case for raising this to High is that the condition is permanent for the session, affects every write, and emits no telemetry.)
Status: Reproducible and persistent. 8 / 8 failures across 3 independent sessions.
Key finding: the same "session settings are unavailable" condition self-heals mid-session for the MCP host but never for memory, which narrows this to a one-shot init with no retry. See §9.1.


1. Summary

The store_memory tool returns a generic failure on every invocation:

Unable to store memory: an unexpected error occurred.

The underlying cause appears in the CLI runtime log at session startup:

[WARNING] [rust:copilot_runtime::shared_api::tools]
Failed to prepare native memory tools {"error":"GenericFailure, session settings are unavailable"}

Critical asymmetry: memory retrieval works, memory persistence does not.
The feature advertises itself as enabled (Memory enablement check: enabled), retrieval succeeds
(memories_count: 1), and store_memory remains exposed to the model as a callable tool — but every
write silently fails. The agent is told to persist a fact, believes memory is available, and the write
is dropped with no actionable error.


2. Environment

Field Value
Copilot CLI version 1.0.81-5
Host wrapper Agency 2026.8.21.9 (commit b9d0abc7, target x86_64-windows)
OS Windows (Windows_NT)
Model Claude Opus 5 (claude-opus-5)
Account https://github.com/tabriggs_microsoft
Context tier long_context
Feature flag MSFT_AGENCY: true
Feature flag enable_memory_voting: true
copilot_pid 3708 (session 2)
engagement_id cd83374c-6384-470b-82d9-52d044f210f9 (session 2)

3. Reproduction

Occurs on every store_memory call. No special input required — failed with both short and long
fact values, with valid scope: "user", and with all required fields populated.

Attempt 1 — 2026-08-24 ~09:0x PDT (session 085853_36868)

{
  "scope": "user",
  "subject": "mcp troubleshooting",
  "fact": "Agency MCP server logs live in %LOCALAPPDATA%\\agency\\logs\\session_{ts}_{pid}\\ — the process-*.log there shows Copilot CLI MCP load/skip decisions.",
  "reason": "<populated, ~3 sentences>",
  "citations": "<populated, file + line refs>"
}

Unable to store memory: an unexpected error occurred.

Attempt 2 — 2026-08-24 ~09:0x PDT (session 085853_36868)

{
  "scope": "user",
  "subject": "mcp troubleshooting",
  "fact": "Locally-configured MCP servers (teams, mail, ado, lynx, charter, bluebird, workiq) are blocked by Copilot CLI's enterprise managed allow list; only builtin + github-mcp-server load.",
  "reason": "<populated, ~3 sentences>",
  "citations": "<populated, file + line refs>"
}

Unable to store memory: an unexpected error occurred.

Attempt 3 — 2026-08-24 12:43 PDT (session 123957_14872) — deliberate probe

{
  "scope": "user",
  "subject": "diagnostics",
  "fact": "DIAGNOSTIC PROBE 2026-08-24T12:43 — testing store_memory availability after earlier failures.",
  "reason": "<populated>",
  "citations": "C:\\Users\\tabriggs\\.copilot\\mcp-config.json"
}

Unable to store memory: an unexpected error occurred.

3 / 3 failures across 2 independent CLI sessions.


4. Root cause evidence

4.1 The failing initialization

Log: C:\Users\tabriggs\AppData\Local\agency\logs\session_20260824_123957_14872\process-1787600410441-3708.log

line 3681:
2026-08-24T19:41:51.342Z [WARNING] [rust:copilot_runtime::shared_api::tools]
  Failed to prepare native memory tools {"error":"GenericFailure, session settings are unavailable"}

Same warning in the earlier session
(session_20260824_085853_36868\process-1787587139218-8816.log):

line 4142:
2026-08-24T15:59:43.710Z [WARNING] [rust:copilot_runtime::shared_api::tools]
  Failed to prepare native memory tools {"error":"GenericFailure, session settings are unavailable"}

Emitted exactly once per session, during startup. There is no retry and no user-visible surfacing.

4.2 Immediate preceding context — probable trigger

The warning fires 918 ms after the managed-settings subsystem fails to resolve a token:

line 3663: 19:41:50.424 [INFO]    [managedSettings] no token available to fetch server policy
                                  — failing closed (bypass stays disabled until policy is known)
line 3664: 19:41:50.424 [INFO]    [managedSettings] effective policy resolved:
                                  source=mdm, bypassDisabled=false, serverFetchFailed=true
line 3665: 19:41:50.424 [WARNING] [managedSettings] sandbox floor only partially determined
                                  (serverUndetermined=true, deviceLoadFailed=false,
                                  deviceSandboxUndetermined=false): no usable token for the selected account
line 3681: 19:41:51.342 [WARNING] Failed to prepare native memory tools
                                  {"error":"GenericFailure, session settings are unavailable"}

Note serverFetchFailed flips falsetrue within the same startup sequence:

line   31: 19:40:21.114  effective policy resolved: source=mdm, serverFetchFailed=false
line   47: 19:40:21.531  no token available to fetch server policy — failing closed
line   48: 19:40:21.531  effective policy resolved: source=mdm, serverFetchFailed=true
line   78: 19:40:22.117  effective policy resolved: source=mdm, serverFetchFailed=false
line  108: 19:40:22.358  no token available to fetch server policy — failing closed
line  109: 19:40:22.358  effective policy resolved: source=mdm, serverFetchFailed=true

This oscillation strongly suggests a startup race: shared_api::tools prepares native memory tools
before session settings are reliably populated, and the "fail closed" path leaves settings in an
unavailable state at exactly that moment.

4.3 Read path works — write path does not

Retrieval succeeds in the same session that failed to prepare memory tools:

{
  "kind": "memory_retrieval",
  "properties": {
    "operation": "getMemoriesPrompt",
    "success": "true",
    "source": "prompt_api",
    "agent": "unspecified",
    "exp_assignment_present": "true",
    "copilot_pid": "3708",
    "engagement_id": "cd83374c-6384-470b-82d9-52d044f210f9"
  },
  "metrics": { "memories_count": 1, "duration_ms": 149 }
}

And the feature reports enabled, repeatedly:

[INFO] [rust:copilot_runtime::tools::api::memory] Memory enablement check: enabled

(19 occurrences across the two sessions.)

So: getMemoriesPrompt via source: prompt_api is healthy, while the native memory tool
preparation path
— which backs store_memory — is dead for the whole session.

4.4 No telemetry emitted for the failures

Searched both session logs for a memory_write / memory_store telemetry kind. None exists.
Only these memory telemetry kinds are emitted:

  • memory_usage
  • memory_exp_assignment_check
  • memory_retrieval

Verification performed:

Select-String '"kind": "(memory[^"]*)"'   →  memory_usage (3), memory_retrieval (2),
                                             memory_exp_assignment_check (2)
Select-String '"kind":.*(store|write)'    →  0 matches
Select-String 'Unable to store memory'    →  0 matches

There is no telemetry event for a failed write, and the string
"Unable to store memory" appears nowhere in the runtime logs — it is generated at the tool
boundary and never logged. This means these failures are invisible to your service-side dashboards.

4.5 The tool remains registered despite failed preparation

Even though native memory tool preparation failed at line 3681, store_memory is still present in the
session's active tool registry and is offered to the model on every turn:

line 7846:       "store_memory:27193c2e",
line 8161:       "store_memory:27193c2e",
line 8464:       "store_memory:27193c2e",
   ... (repeated every turn)

This is the mechanism behind the silent failure: preparation fails once at startup, but the tool is
advertised to the model regardless, so the agent calls it in good faith and the write is dropped.


5. Correlated defect (same root cause, different symptom)

The identical session settings are unavailable condition also caused every user-configured MCP
server to be stripped from the session, 918 ms before the memory tool failure:

19:41:50.425 [DEBUG] [rust:copilot_runtime::session::mcp::agent_host]
  Skipping MCP server "lynx": not permitted by enterprise managed allow list {"agent":""}

In session 085853_36868 this hit teams, mail, ado, lynx, charter — all skipped.
Those servers had already started and successfully authenticated (Entra token acquired,
initialize + notifications/initialized returned HTTP 202) before being discarded.

The same servers loaded normally later in the day without any configuration change, which is further
evidence of a non-deterministic startup race rather than a genuine policy denial.

Sharpened by §9.1. In session 090714_24084 the skipped servers recovered inside the same
live session
, 2h15m after being refused, with no restart and no config change, while
store_memory stayed broken for the session's full duration. The two defects share a trigger but
differ in recovery: the MCP host re-evaluates, memory tool preparation never does.

Suggested fix scope: whatever guarantees session settings are resolved before
copilot_runtime::shared_api::tools and copilot_runtime::session::mcp::agent_host consume them.


6. Impact

  1. Silent data loss. Every fact the agent is instructed to persist is discarded. The user's global
    instructions rely on memory for cross-session conventions; none of it survives.
  2. Misleading agent behavior. store_memory stays exposed as a callable tool and memory
    retrieval works, so the agent has no signal that writes are broken. It will tell users
    "I'll remember that" and be wrong.
  3. Unactionable error text. "an unexpected error occurred" gives the user nothing. The real
    cause is only recoverable by grepping runtime logs.
  4. Invisible to service telemetry. No failure event is emitted (§4.4), so this will not appear
    in reliability metrics.

7. Requested actions

  1. Fix the race — ensure session settings are available before native memory tool preparation, or
    retry preparation once settings resolve instead of failing once at startup with no recovery.
    (§9.7: the retry is the higher-value fix and should be the primary ask. The runtime already
    re-resolves these settings mid-session for the MCP host; memory should subscribe to that same
    event.)
  2. Surface the failure — propagate the real cause (session settings are unavailable) into the
    tool result instead of "an unexpected error occurred".
  3. Do not advertise a broken tool — if native memory tools fail to prepare, either withhold
    store_memory from the tool list or have it return an explicit "memory unavailable this session"
    so the agent can warn the user rather than silently dropping writes.
  4. Add write telemetry — emit a memory_write event with success/failure so this is observable
    service-side.
  5. Investigate the serverFetchFailed oscillation (§4.2) as the likely upstream trigger for both
    this and the MCP allow-list defect (§5).

8. Attachments to request from the reporter

Full runtime logs (large; contain session transcripts — review before sharing):

  • C:\Users\tabriggs\AppData\Local\agency\logs\session_20260824_123957_14872\process-1787600410441-3708.log
    (~270 KB — memory tool failure at line 3681)
  • C:\Users\tabriggs\AppData\Local\agency\logs\session_20260824_085853_36868\process-1787587139218-8816.log
    (~4.98 MB — memory tool failure at line 4142, MCP allow-list skips at lines 152–156)

Managed-settings inputs (no secrets):

  • HKLM\SOFTWARE\Policies\GitHubCopilot → keys: remoteControl.mode=requireSSO,
    remoteControl.githubEnterpriseCloudDomains, remoteControl.githubDotComOrganizations
  • C:\Program Files\GitHubCopilot\managed-settings.jsondoes not exist
    (logged as [MDM] No managed settings found)
  • C:\Users\tabriggs\.copilot\m-mcp-servers.json → contains only builtin filesystem and playwright

9. Addendum: third session, and evidence that settings DO recover while memory does not

Added 2026-08-24 ~12:50 PDT from a third, independent CLI session running concurrently with the
two above. This session was a long-running Responsible AI release assessment review, roughly 3 hours
40 minutes end to end.

Field Value
Session session_20260824_090714_24084
Runtime log process-1787587640175-6664.log (68,037,664 bytes)
copilot_pid 6664
engagement_id f7f39347-7785-475c-a2e7-bc733a4e9b0c
Session window 09:07:14 to 12:49+ PDT
store_memory attempts 5, all failed
Running total 8 / 8 failures across 3 independent sessions

Same warning, same wording, same startup-only emission:

line 271:
2026-08-24T16:07:54.534Z [WARNING] [rust:copilot_runtime::shared_api::tools]
  Failed to prepare native memory tools {"error":"GenericFailure, session settings are unavailable"}

9.1 The decisive finding: the MCP defect self-healed mid-session, memory did not

Section 5 treats the MCP allow-list defect and the memory-tool defect as the same root cause. This
session shows they share a trigger but have very different recovery behavior, and that
difference is the strongest available evidence for requested action #1.

At startup, this session stripped MCP servers exactly as described in section 5. There were 29
runtime allow-list skips
, the last at 16:07:54.988Z, covering ado, mail, teams, lynx,
charter, bluebird, workiq, and computer-use.

Then, 2 hours 15 minutes later and with no configuration change, no restart, and no user action,
every one of those servers became available inside the same live session.
The runtime pushed a
tool-change notification to the model at 2026-08-24T10:23:19.908-07:00 announcing ado-*, mail-*,
teams-*, lynx-*, charter-*, bluebird-*, and workiq-*. They were used successfully for the
rest of the session.

store_memory never recovered. Two of the five failed attempts happened before the MCP
recovery, and three happened after it, including attempts at roughly 10:29, 10:30, and 12:47 PDT.

This matters because it removes the benign explanation. The session settings that were
"unavailable" at 16:07:54.534Z demonstrably became available later in the same process, since
the MCP host re-evaluated policy and admitted seven servers it had previously refused. The memory
subsystem simply never looked again:

MCP allow-list path Native memory tool path
Fails at startup on unavailable settings Yes Yes
Re-evaluates later in the session Yes, recovered at 10:23:19 PDT No. Dead for the full session
User-visible signal on recovery Yes, tool-change notification n/a, never recovers

So this is not an enterprise policy genuinely denying memory writes, and it is not a persistent
environment problem. It is a one-shot initialization that fails during a startup race and has no
retry
, in a runtime that already demonstrates it can re-resolve the very same settings later.

Fixing this may be as cheap as re-running memory tool preparation on the same event that causes the
MCP host to re-evaluate.
That path already exists and already works.

9.2 Timing delta varies between sessions, which further indicates a race

The gap between the sandbox floor only partially determined warning and the memory failure is not
constant:

Session Sandbox warning Memory failure Delta
123957_14872 19:41:50.424Z 19:41:51.342Z 918 ms
090714_24084 16:07:53.924Z 16:07:54.534Z 610 ms

A fixed dependency failure would not vary. A race would.

This session also shows the serverFetchFailed oscillation described in 4.2, with an additional
early signal worth noting:

16:07:25.868  server policy fetch skipped: no authenticated GitHub host available
16:07:25.868  effective policy resolved: source=mdm, serverFetchFailed=false
16:07:26.132  no token available to fetch server policy - failing closed
16:07:26.132  effective policy resolved: source=mdm, serverFetchFailed=true
16:07:26.562  confirmed no policy served from fresh cache (age 1219099ms) from https://github.com
16:07:26.562  effective policy resolved: source=mdm, serverFetchFailed=false
16:07:26.848  no token available to fetch server policy - failing closed
16:07:26.848  effective policy resolved: source=mdm, serverFetchFailed=true

serverFetchFailed flips false, true, false, true in under one second. The runtime starts
resolving policy before an authenticated GitHub host exists, which looks like the upstream trigger
for both defects.

9.3 Correction and reinforcement of section 4.4

Section 4.4 states the string "Unable to store memory" appears nowhere in the runtime logs.
In this session it appears 230 times, but the underlying claim is still correct and should not be
withdrawn.
The distinction matters, because a reviewer running a naive grep will see 230 hits and
may wrongly dismiss the finding.

Verified breakdown:

Total occurrences of "Unable to store memory"        : 230
Occurrences that are actual runtime log lines        :   0
  (i.e. matching ^<ISO timestamp> ... [INFO|WARNING|ERROR|DEBUG])

All 230 are conversation transcript payload, serialized as
"content": "Unable to store memory: an unexpected error occurred.", and replayed into the log on
every subsequent turn as chat history. The runtime itself still logs nothing when a memory write
fails.

Telemetry findings match section 4.4 exactly:

"kind": "memory_write"  ->  0 matches
"kind": "memory_store"  ->  0 matches
"kind": "memory_retrieval" -> 18 events, all success
Memory enablement check: enabled -> 9 runtime occurrences

9.4 Read path is healthy, with real data

Retrieval worked throughout, and unlike session 2 (memories_count: 1) this account returned a
populated set:

{ "kind": "memory_retrieval",
  "properties": { "success": "true", "copilot_pid": "6664",
                  "engagement_id": "f7f39347-7785-475c-a2e7-bc733a4e9b0c" },
  "metrics": { "memories_count": 6, "duration_ms": 104 } }

18 successful retrievals, 0 successful writes, in one session. The asymmetry in section 1 is
reproduced exactly.

9.5 Observed user-facing harm

This is the concrete version of impact item 2, and it is worth attaching to the bug because it shows
the failure mode reaching the user rather than staying internal.

Mid-session the user gave an explicit, direct instruction to persist a correction:

"FYI we don't do System Information Assessments anymore. Store that in your memory to update
whichever SOP you're going off of."

The write failed. It was retried once and failed again. Two further corrections the user issued in
the same session, about harm-taxonomy scope and about an email-drafting defect, also failed to
persist.

Because the CLI reports memory as enabled and retrieval succeeds, the only reason these corrections
were not lost is that the agent noticed the repeated tool errors and manually wrote the content into
version-controlled repository files instead.
An agent that trusted the tool, or a user who did not
read the tool output, would have been told the preference was remembered when it was not. That is the
exact failure the user's own global instructions warn about: "'Got it, I'll remember' without a tool
call is a bug."
Here the tool call was made in good faith and dropped anyway.

Note also that 5 failures in one session produced 5 identical, non-actionable error strings, with
no escalation, no changed message, and no hint that the condition was session-wide and permanent.

9.6 Additional attachment

  • C:\Users\tabriggs\AppData\Local\agency\logs\session_20260824_090714_24084\process-1787587640175-6664.log
    (~68 MB, contains full session transcript, review before sharing)
    • memory tool failure: line 271
    • managed-settings oscillation: lines 1 to 120
    • MCP allow-list skips: lines 150 to 413 (29 runtime skips)
    • MCP recovery notification: line 213507 (2026-08-24T10:23:19.908-07:00)

9.7 Amended request

Section 7 item 1 asks to fix the race or retry preparation once settings resolve. Based on 9.1,
the retry is the higher-value fix and should be treated as the primary ask. The runtime already
re-evaluates these settings successfully mid-session for the MCP host. Memory tool preparation should
subscribe to that same resolution event rather than failing once at startup and staying dead for
hours.

Section 7 item 3 also gains urgency: with 8 consecutive failures across 3 sessions, the tool stayed
advertised every single turn. Withholding it, or returning memory unavailable this session, would
have let the agent warn the user on the first failure instead of the user discovering it after the
fact.


10. Addendum: 2026-08-25 — day 3, restart does NOT clear it, and platform-team confirmation

Added 2026-08-25 ~11:15 PDT. The defect persisted into a third consecutive day and, critically,
survived a full terminal restart — which rules out the "transient startup race that clears on
relaunch" mitigation implied in §5.

10.1 New environment delta

Field 8/24 value 8/25 value
Copilot CLI 1.0.81-5 1.0.81-5 (unchanged)
Agency host 2026.8.21.9 (b9d0abc7) 2026.8.24.6 (290b8f85) — upgraded, defect persists
Model Claude Opus 5 Claude Opus 5

The Agency host was upgraded between 8/24 and 8/25. The defect is unaffected, which further
isolates it to the Copilot CLI runtime rather than the Agency wrapper.

10.2 store_memory — 3 more failures, now 11 / 11 lifetime

Three additional store_memory calls were attempted on 8/25 in session 103633_48160, all with
valid scope: "user", populated subject / fact / reason / citations. All three returned:

Unable to store memory: an unexpected error occurred.

Running total: 11 / 11 failures across 4 independent sessions, 2 Agency host versions, 2 days.

10.3 The correlated MCP defect (§5) got materially worse — total strip

On 8/25 the enterprise-managed-allow-list skip did not merely hit some servers; it stripped
every user-configured and auto-injected MCP server, including the builtin browser tooling.

Per-session counts of not permitted by enterprise managed allow list on 2026-08-25:

session_20260825_103540_28160  |  allowlist-skips=29  memtool-fail=1  no-token=4
session_20260825_103630_40448  |  allowlist-skips=29  memtool-fail=1  no-token=4
session_20260825_103633_48160  |  allowlist-skips=31  memtool-fail=7  no-token=10
session_20260825_110352_9484   |  allowlist-skips=29  memtool-fail=1  no-token=4   <-- AFTER RESTART

Verbatim, from session_20260825_110352_9484\process-1787681037541-57080.log:

2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "ado": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "teams": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "lynx": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "charter": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:04:53.298Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "mail": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:05:06.119Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "computer-use": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:05:06.119Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "teams": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:05:06.119Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "charter": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:05:06.119Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "workiq": not permitted by enterprise managed allow list {"agent":""}
2026-08-25T18:05:06.119Z [DEBUG] [rust:copilot_runtime::session::mcp::agent_host] Skipping MCP server "bluebird": not permitted by enterprise managed allow list {"agent":""}

Note bluebird and workiq are Agency auto-injected defaults, and computer-use is builtin —
so this is not limited to user-supplied servers in ~/.copilot/mcp-config.json.

10.4 The same managedSettings oscillation, same session, after restart

2026-08-25T18:04:05.899Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=false
2026-08-25T18:04:06.277Z [managedSettings] no token available to fetch server policy — failing closed (bypass stays disabled until policy is known)
2026-08-25T18:04:06.277Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=true
2026-08-25T18:04:06.672Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=false
2026-08-25T18:04:07.032Z [managedSettings] no token available to fetch server policy — failing closed (bypass stays disabled until policy is known)
2026-08-25T18:04:07.032Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=true
2026-08-25T18:05:06.985Z [managedSettings] effective policy resolved: source=mdm, bypassDisabled=false, serverFetchFailed=false
2026-08-25T18:05:07.316Z [managedSettings] no token available to fetch server policy — failing closed (bypass stays disabled until policy is known)

serverFetchFailed oscillates false → true → false → true exactly as described in §4.2. The MCP
allow-list evaluation and the native-memory-tool preparation both consume this value while it is
mid-flap, and both fail closed. This is the single upstream trigger for both defects.

10.5 Platform-team confirmation (rules out the MCP servers themselves)

The Microsoft MCP Platform team investigated the server side and ruled it out. Email from
Pardhu Vavila (MCP Platform Dev), 2026-08-25:

Hi Tanner,

Looks like the store_memory tool seems to be the cause of these issues, this is not originating
from our mcp servers

You can reach out for support from Agency here: Agency | Community in Viva Engage

And also can raise an issue on copilot cli here : Issues · github/copilot-cli (I see few issues
with store_memory here)

Thanks,
Pardhu

Preceded by his 2026-08-24 acknowledgement on the thread *"MCP tools fail to register in Copilot CLI

  • 60s init timeout, 84% of sessions since 8/17"* (to mcpplat@microsoft.com, cc cuturn@).

This is an independent confirmation of §5: the MCP servers start correctly and authenticate
successfully; the Copilot CLI discards them afterward. Two separate teams have now arrived at the
same conclusion from opposite directions.

10.6 A rate-limiting red herring, documented so others don't repeat it

Before the allow-list evidence was found, the 8/25 investigation pursued HTTP 429 rate-limiting as
the cause. That signal is real but is not the cause of the tool dropout:

Upstream returned transient status; will retry attempt=1..4 status=429 method=tools/list
{"code":-32001,"message":"Remote connection error: Upstream MCP server returned HTTP status 429 Too Many Requests"}

372 such events across 5 days (mail 297 / teams 75). However, the session whose tools actually
vanished logged zero 429s — its proxy log ends on a successful exchange. The 429s are a separate,
lower-severity upstream capacity issue. Anyone triaging this should not be misled by them: the
decisive string is not permitted by enterprise managed allow list, in process-*.log, not in
the agency_mcp_*.log proxy logs.

10.7 Updated severity argument

§9.1 argued for High on the memory defect alone. The 8/25 data strengthens it:

  1. Not self-limiting — persisted across 2 Agency host versions, 4+ sessions, 2+ days.
  2. Restart is not a workaround — the post-restart session shows identical behavior.
  3. Blast radius is larger than memory — the same trigger removes every MCP server, including
    auto-injected and builtin ones, silently disabling entire agent workflows. In this case it
    blocked a production compliance-outreach workflow (Regulated Industry Minimum Bar) from running
    at all.
  4. Still no telemetry (§4.4) — none of this is visible service-side.

11. Full evidence appendix — every session, both days

Added 2026-08-25 ~11:35 PDT. Machine-generated from process-*.log across all Copilot CLI
sessions on 2026-08-24 and 2026-08-25. Filtered to the four diagnostic signatures only — no session
transcripts, no prompt/response content, no customer or business data
.

Signatures counted:

  • Skipping MCP server "<name>": not permitted by enterprise managed allow list
  • Failed to prepare native memory tools {"error":"GenericFailure, session settings are unavailable"}
  • [managedSettings] no token available to fetch server policy — failing closed
  • feature flags copilot_cli_mcp_allowlist, copilot_cli_mcp_enterprise_allowlist
Session Allow-list skips Servers skipped Memory-tool prep failures no token events
session_20260824_063132_28764 16 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 1 4
session_20260824_074600_27636 29 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 1 4
session_20260824_082433_8096 29 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 1 4
session_20260824_085853_36868 180 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 82 129
session_20260824_090141_36848 29 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 1 4
session_20260824_090714_24084 59 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 123 45
session_20260824_123957_14872 29 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 1 4
session_20260825_103540_28160 29 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 1 4
session_20260825_103630_40448 29 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 1 4
session_20260825_103633_48160 741 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 377 654
session_20260825_110352_9484 242 ado, bluebird, charter, computer-use, lynx, mail, teams, workiq 1 116

Totals: 1,412 allow-list skips, 590 memory-tool preparation failures, 972 no token events across
11 sessions over 2 days.

11.1 What this table proves

  1. Universal, not intermittent at session scope. Every single session on both days hit it. There
    is no clean session in the sample.
  2. Identical server set every time — the same 8 servers, including auto-injected (bluebird,
    workiq) and builtin (computer-use). This is not a user-config problem.
  3. Restart is not a remedy. session_20260825_110352_9484 is a deliberate post-restart session
    and shows 242 skips and 116 no token events.
  4. The two defects co-occur without exception. Every session with allow-list skips also has
    memory-tool preparation failures. Same trigger, as argued in §4.2 and §10.4.
  5. Repetition within a session. The counts far exceed one-per-server, so the allow-list path is
    re-evaluated many times per session and fails closed each time.

11.2 Racy at server scope — the critical nuance

Although the skip line is logged for all 8 servers, the outcome is not uniform. In one 8/25 session
teams, workiq, bluebird and charter were logged as skipped and still ended up connected,
while mail was skipped on all three passes and never registered.

A partially-working MCP fleet does NOT exonerate the allow list. Triagers should grep for the
per-server skip line rather than inferring from which servers happen to be up.

11.3 Diagnostic guidance for triagers — read the right log

Three log files exist per session and they answer different questions. Getting this wrong cost this
investigation two wrong root causes (a 429 rate-limit theory and a 502 startup-race theory):

File Owner Tells you
agency_copilot_*.log Agency host Whether config loaded, which servers resolved, proxy + handshake
agency_mcp_<name>_*.log That MCP server Its own startup, auth, upstream errors
process-*.log Copilot CLI runtime The allow list and final tool registration — authoritative

Agency will report a server as loaded, resolved, ready, authenticated and handshaking is_error=false
while the CLI has already discarded it. The decisive command is:

Select-String -Path "$sessionDir\process-*.log" -Pattern 'Skipping MCP server'

11.4 Two red herrings, documented so they aren't repeated

  • HTTP 429 rate limiting. 372 upstream status=429 method=tools/list events across 5 days
    (mail 297 / teams 75) are real but not the cause — the session whose tools vanished logged
    zero 429s and its proxy log ends on a successful exchange.
  • A 502 startup race. mail once took status=502 method=initialize into retry backoff and
    finished its handshake ~24s after every other server — slowest server, only missing server, clean
    story, and wrong. It had already been discarded at 18:04:53, before that handshake completed.

Both were discarded only after reading process-*.log.

11.5 Operational impact, concretely

This blocked a production compliance workflow (Regulated Industry Minimum Bar) from running on three
consecutive days. That workflow depends on mail, teams, ado and workiq to sync Azure DevOps
assessments and send owner outreach. Two full runs were aborted at the pre-flight check
(logged as Run #41 and Run #42) with zero work performed.

Degraded-mode fallbacks exist (Azure CLI az boards for ADO, Outlook COM for mail) but are
substantially slower and have their own documented failure modes.

11.6 Raw log locations (available on request)

Full logs were not attached because they contain complete session transcripts. They can be
provided to GitHub staff on request, ideally via a private channel:

%LOCALAPPDATA%\agency\logs\session_20260825_103633_48160\process-*.log
%LOCALAPPDATA%\agency\logs\session_20260825_110352_9484\process-*.log     (post-restart)
%LOCALAPPDATA%\agency\logs\session_20260824_085853_36868\process-*.log
%LOCALAPPDATA%\agency\logs\session_20260824_090714_24084\process-*.log    (mid-session MCP recovery)

Managed-settings inputs (no secrets):

  • HKLM\SOFTWARE\Policies\GitHubCopilotremoteControl.mode=requireSSO,
    remoteControl.githubEnterpriseCloudDomains, remoteControl.githubDotComOrganizations
  • C:\Program Files\GitHubCopilot\managed-settings.jsondoes not exist ([MDM] No managed settings found)
  • C:\Users\tabriggs\.copilot\m-mcp-servers.json → builtin filesystem + playwright only
  • C:\Users\tabriggs\.copilot\mcp-config.json → 4 servers, valid JSON, no BOM, last modified 7/27/2026

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:context-memoryContext window, memory, compaction, checkpoints, and instruction loadingarea:enterpriseGitHub Enterprise (GHE/GHES) support, org policies, and enterprise settingsarea:mcpMCP server configuration, discovery, connectivity, OAuth, policy, and registry

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions