@@ -17,6 +17,7 @@ import * as fs from 'fs-extra';
1717import * as os from 'os' ;
1818import * as path from '../../platform/vscode-path/path' ;
1919import { generateUuid } from '../../platform/common/uuid' ;
20+ import { DeepnoteServerStartupError , DeepnoteServerTimeoutError } from '../../platform/errors/deepnoteKernelErrors' ;
2021
2122/**
2223 * Lock file data structure for tracking server ownership
@@ -41,6 +42,8 @@ export class DeepnoteServerStarter implements IDeepnoteServerStarter, IExtension
4142 private readonly sessionId : string = generateUuid ( ) ;
4243 // Directory for lock files
4344 private readonly lockFileDir : string = path . join ( os . tmpdir ( ) , 'vscode-deepnote-locks' ) ;
45+ // Track server output for error reporting
46+ private readonly serverOutputByFile : Map < string , { stdout : string ; stderr : string } > = new Map ( ) ;
4447
4548 constructor (
4649 @inject ( IProcessServiceFactory ) private readonly processServiceFactory : IProcessServiceFactory ,
@@ -175,15 +178,27 @@ export class DeepnoteServerStarter implements IDeepnoteServerStarter, IExtension
175178 const disposables : IDisposable [ ] = [ ] ;
176179 this . disposablesByFile . set ( fileKey , disposables ) ;
177180
181+ // Initialize output tracking for error reporting
182+ this . serverOutputByFile . set ( fileKey , { stdout : '' , stderr : '' } ) ;
183+
178184 // Monitor server output
179185 serverProcess . out . onDidChange (
180186 ( output ) => {
187+ const outputTracking = this . serverOutputByFile . get ( fileKey ) ;
181188 if ( output . source === 'stdout' ) {
182189 logger . trace ( `Deepnote server (${ fileKey } ): ${ output . out } ` ) ;
183190 this . outputChannel . appendLine ( output . out ) ;
191+ if ( outputTracking ) {
192+ // Keep last 5000 characters of output for error reporting
193+ outputTracking . stdout = ( outputTracking . stdout + output . out ) . slice ( - 5000 ) ;
194+ }
184195 } else if ( output . source === 'stderr' ) {
185196 logger . warn ( `Deepnote server stderr (${ fileKey } ): ${ output . out } ` ) ;
186197 this . outputChannel . appendLine ( output . out ) ;
198+ if ( outputTracking ) {
199+ // Keep last 5000 characters of error output for error reporting
200+ outputTracking . stderr = ( outputTracking . stderr + output . out ) . slice ( - 5000 ) ;
201+ }
187202 }
188203 } ,
189204 this ,
@@ -206,13 +221,30 @@ export class DeepnoteServerStarter implements IDeepnoteServerStarter, IExtension
206221 try {
207222 const serverReady = await this . waitForServer ( serverInfo , 120000 , token ) ;
208223 if ( ! serverReady ) {
224+ const output = this . serverOutputByFile . get ( fileKey ) ;
209225 await this . stopServerImpl ( deepnoteFileUri ) ;
210- throw new Error ( 'Deepnote server failed to start within timeout period' ) ;
226+
227+ throw new DeepnoteServerTimeoutError ( serverInfo . url , 120000 , output ?. stderr || undefined ) ;
211228 }
212229 } catch ( error ) {
213230 // Clean up leaked server before rethrowing
214231 await this . stopServerImpl ( deepnoteFileUri ) ;
215- throw error ;
232+
233+ // If this is already a DeepnoteKernelError, rethrow it
234+ if ( error instanceof DeepnoteServerTimeoutError || error instanceof DeepnoteServerStartupError ) {
235+ throw error ;
236+ }
237+
238+ // Otherwise wrap in a generic server startup error
239+ const output = this . serverOutputByFile . get ( fileKey ) ;
240+ throw new DeepnoteServerStartupError (
241+ interpreter . uri . fsPath ,
242+ port ,
243+ 'unknown' ,
244+ output ?. stdout || '' ,
245+ output ?. stderr || '' ,
246+ error instanceof Error ? error : undefined
247+ ) ;
216248 }
217249
218250 logger . info ( `Deepnote server started successfully at ${ url } for ${ fileKey } ` ) ;
@@ -261,6 +293,7 @@ export class DeepnoteServerStarter implements IDeepnoteServerStarter, IExtension
261293 serverProcess . proc ?. kill ( ) ;
262294 this . serverProcesses . delete ( fileKey ) ;
263295 this . serverInfos . delete ( fileKey ) ;
296+ this . serverOutputByFile . delete ( fileKey ) ;
264297 this . outputChannel . appendLine ( `Deepnote server stopped for ${ fileKey } ` ) ;
265298
266299 // Clean up lock file after stopping the server
@@ -381,6 +414,7 @@ export class DeepnoteServerStarter implements IDeepnoteServerStarter, IExtension
381414 this . serverInfos . clear ( ) ;
382415 this . disposablesByFile . clear ( ) ;
383416 this . pendingOperations . clear ( ) ;
417+ this . serverOutputByFile . clear ( ) ;
384418
385419 logger . info ( 'DeepnoteServerStarter disposed successfully' ) ;
386420 }
0 commit comments