mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 03:30:40 +00:00
fix: Strengthen error handling in qwenOAuth2.ts to prevent unhandled 'error' event (#3481)
* fix: strengthen error handling in launchBrowser to prevent unhandled events * fix: strengthen error handling with ChildProcess type and debugLogger * fix: use type-only import for ChildProcess
This commit is contained in:
parent
53293e4d85
commit
5c1e636dbe
1 changed files with 27 additions and 19 deletions
|
|
@ -8,7 +8,7 @@ import crypto from 'crypto';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { promises as fs } from 'node:fs';
|
import { promises as fs } from 'node:fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
import type { ChildProcess } from 'node:child_process';
|
||||||
import open from 'open';
|
import open from 'open';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import type { Config } from '../config/config.js';
|
import type { Config } from '../config/config.js';
|
||||||
|
|
@ -489,10 +489,10 @@ export enum QwenOAuth2Event {
|
||||||
export type AuthResult =
|
export type AuthResult =
|
||||||
| { success: true }
|
| { success: true }
|
||||||
| {
|
| {
|
||||||
success: false;
|
success: false;
|
||||||
reason: 'timeout' | 'cancelled' | 'error' | 'rate_limit';
|
reason: 'timeout' | 'cancelled' | 'error' | 'rate_limit';
|
||||||
message?: string; // Detailed error message for better error reporting
|
message?: string; // Detailed error message for better error reporting
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global event emitter instance for QwenOAuth2 authentication events
|
* Global event emitter instance for QwenOAuth2 authentication events
|
||||||
|
|
@ -717,26 +717,34 @@ async function authWithQwenDeviceFlow(
|
||||||
|
|
||||||
// Helper to handle browser launch with error handling
|
// Helper to handle browser launch with error handling
|
||||||
const launchBrowser = async (url: string): Promise<void> => {
|
const launchBrowser = async (url: string): Promise<void> => {
|
||||||
try {
|
let childProcess: ChildProcess | undefined;
|
||||||
const childProcess = await open(url);
|
|
||||||
|
|
||||||
// IMPORTANT: Attach an error handler to the returned child process.
|
try {
|
||||||
// Without this, if `open` fails to spawn a process (e.g., `xdg-open` is not found
|
// Call open and get the process
|
||||||
// in a minimal Docker container), it will emit an unhandled 'error' event,
|
childProcess = await open(url);
|
||||||
// causing the entire Node.js process to crash.
|
|
||||||
if (childProcess) {
|
// CRITICAL FIX: Attach error listener IMMEDIATELY if a process object exists.
|
||||||
childProcess.on('error', (err) => {
|
// We do this outside the 'if' check scope to ensure it's bound as soon as possible.
|
||||||
debugLogger.debug('Browser launch failed:', err.message || err);
|
if (childProcess && typeof childProcess.on === 'function') {
|
||||||
|
childProcess.on('error', (err: Error) => {
|
||||||
|
debugLogger.warn(`Browser launch process error: ${err.message}`);
|
||||||
|
debugLogger.info(`Please open this URL manually: ${url}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Optional: Also listen for 'close' or 'exit' if needed for cleanup,
|
||||||
|
// but 'error' is the main crasher.
|
||||||
|
} else {
|
||||||
|
// Fallback: If open() didn't return a valid process object, log a warning
|
||||||
|
debugLogger.debug('open() did not return a valid child process object.');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
debugLogger.debug(
|
// Handle synchronous errors or promise rejections from open()
|
||||||
'Failed to open browser:',
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
||||||
err instanceof Error ? err.message : 'Unknown error',
|
debugLogger.warn(`Failed to open browser automatically: ${errorMessage}`);
|
||||||
);
|
debugLogger.info(`Please open this URL manually: ${url}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Generate PKCE code verifier and challenge
|
// Generate PKCE code verifier and challenge
|
||||||
const { code_verifier, code_challenge } = generatePKCEPair();
|
const { code_verifier, code_challenge } = generatePKCEPair();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue