microsoft/vscode · error · Error
Missing API key for custom URL (${this.urlOrRequestMetadata}
Error message
Missing API key for custom URL (${this.urlOrRequestMetadata}). Provide the API key using vscode setting `github.copilot.chat.advanced.inlineEdits.xtabProvider.apiKey` or, if in simulations using `--nes-api-key` or `--config-file` What it means
XtabEndpoint is a ChatEndpoint subclass for the cross-tab (xtab) inline-edits provider, a TeamInternal feature pointing at a custom/self-hosted URL. Its getExtraHeaders() must attach a Bearer/api-key Authorization header to every request. The key is resolved from three sources in priority order: the config setting github.copilot.chat.advanced.inlineEdits.xtabProvider.apiKey, then the constructor _apiKey argument, then (for simulations) --nes-api-key/--config-file. If all are empty/falsy, it logs to console.error and throws, because an unauthenticated request to the custom endpoint would fail anyway.
Source
Thrown at extensions/copilot/src/extension/xtab/node/xtabEndpoint.ts:92
_instantiationService,
_configService,
_experimentationService,
_chatWebSocketService,
_logService
);
}
override get urlOrRequestMetadata(): string {
return this._configService.getConfig(ConfigKey.TeamInternal.InlineEditsXtabProviderUrl) || this._url;
}
public override getExtraHeaders(): Record<string, string> {
const apiKey = this._configService.getConfig(ConfigKey.TeamInternal.InlineEditsXtabProviderApiKey) || this._apiKey;
if (!apiKey) {
const message = `Missing API key for custom URL (${this.urlOrRequestMetadata}). Provide the API key using vscode setting \`github.copilot.chat.advanced.inlineEdits.xtabProvider.apiKey\` or, if in simulations using \`--nes-api-key\` or \`--config-file\``;
console.error(message);
throw new Error(message);
}
return {
'Authorization': `Bearer ${apiKey}`,
'api-key': apiKey,
};
}
}
View on GitHub (pinned to a94b963a32)
Solutions
- Set the VS Code setting github.copilot.chat.advanced.inlineEdits.xtabProvider.apiKey to the provider's API key (matching the configured InlineEditsXtabProviderUrl).
- If running a simulation, pass --nes-api-key <key> or --config-file <path-to-config-with-key>.
- If constructing XtabEndpoint directly, supply a non-empty apiKey as the second constructor argument.
- Verify the setting is in the correct scope (user vs workspace) and the key is not being overridden to empty by a higher-priority config source.
Example fix
// before — endpoint constructed without a key and no config setting
const endpoint = instantiationService.createInstance(XtabEndpoint, customUrl, '', undefined);
endpoint.getExtraHeaders(); // throws
// after — pass the key explicitly (or set the config setting)
const endpoint = instantiationService.createInstance(XtabEndpoint, customUrl, process.env.XTAB_API_KEY ?? '', undefined);
endpoint.getExtraHeaders(); // { Authorization: 'Bearer ...', 'api-key': '...' }
// or via settings.json:
// "github.copilot.chat.advanced.inlineEdits.xtabProvider.apiKey": "<your-key>" Defensive patterns
Strategy: validation
Validate before calling
function resolveXtabApiKey(configService: IConfigurationService, ctorKey: string): string | undefined {
return configService.getConfig(ConfigKey.TeamInternal.InlineEditsXtabProviderApiKey)
|| ctorKey
|| process.env.NES_API_KEY
|| undefined;
}
// before triggering an inline edit / calling getExtraHeaders():
const key = resolveXtabApiKey(configService, endpointCtorApiKey);
if (!key) {
throw new Error('xtab provider selected but no API key configured; set github.copilot.chat.advanced.inlineEdits.xtabProvider.apiKey');
} Type guard
function hasXtabCredentials(configService: IConfigurationService, ctorKey: string): boolean {
return Boolean(
configService.getConfig(ConfigKey.TeamInternal.InlineEditsXtabProviderApiKey)
|| ctorKey
|| process.env.NES_API_KEY
);
} Try / catch
try {
const headers = endpoint.getExtraHeaders();
// attach headers to the fetch request
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
if (msg.startsWith('Missing API key for custom URL')) {
// fall back to the default Copilot endpoint OR surface a user-actionable notice;
// do NOT retry identically — the config must change first
showWarningMessage('Set github.copilot.chat.advanced.inlineEdits.xtabProvider.apiKey to use the custom xtab provider.');
return;
}
throw e;
} Prevention
- Always provision InlineEditsXtabProviderApiKey whenever InlineEditsXtabProviderUrl is set — they are a pair.
- In simulations, always pass --nes-api-key or a --config-file that includes the key.
- Guard with hasXtabCredentials() before enabling the xtab code path so the failure is detected at config time, not mid-request.
- Keep the API key in the user settings or a secrets store; never hard-code it in workspace settings that may be committed.
When it happens
Trigger: getExtraHeaders() is called during an inline-edit request to the xtab provider when ConfigKey.TeamInternal.InlineEditsXtabProviderApiKey is unset AND the endpoint was constructed with an empty _apiKey AND no simulation flag supplied a key. The check at xtabEndpoint.ts:89 fails and the throw at line 92 fires, embedding the resolved URL (urlOrRequestMetadata) in the message.
Common situations: A TeamInternal user enabled the custom xtab provider URL (InlineEditsXtabProviderUrl) but forgot the matching apiKey setting; the setting key was typo'd or scoped to the wrong workspace; a local dev/simulation run omitted --nes-api-key; a config-file override cleared the key; the feature was toggled on by an experiment without the operator provisioning credentials.
Related errors
AI-assisted analysis of microsoft/vscode@a94b963a32 (2026-08-12).
Data as JSON: /api/errors/2d5451bd35f0cc4f.
Report an issue: GitHub.