@@ -629,23 +629,42 @@ async function installPackage(packageInfo) {
629629 const pkgJsonPath = path . join ( extractedPath , 'package.json' )
630630
631631 // Verify package.json exists and is not empty.
632- const pkgJsonStats = await fs . stat ( pkgJsonPath )
633- if ( pkgJsonStats . size === 0 ) {
634- throw new Error ( 'Extracted package.json is empty' )
632+ // Retry up to 3 times to handle filesystem flush delays on slow CI systems.
633+ let editablePkgJson
634+ let lastError
635+ for ( let attempt = 1 ; attempt <= 3 ; attempt += 1 ) {
636+ try {
637+ // eslint-disable-next-line no-await-in-loop
638+ const pkgJsonStats = await fs . stat ( pkgJsonPath )
639+ if ( pkgJsonStats . size === 0 ) {
640+ throw new Error ( 'Extracted package.json is empty' )
641+ }
642+
643+ // Remove the "files" field so pnpm includes all files (including tests).
644+ // Also remove unnecessary lifecycle scripts that could interfere with testing.
645+ // eslint-disable-next-line no-await-in-loop
646+ editablePkgJson = await readPackageJson ( pkgJsonPath , {
647+ editable : true ,
648+ } )
649+ break
650+ } catch ( error ) {
651+ lastError = error
652+ if ( attempt < 3 ) {
653+ // Wait longer on each retry (200ms, 400ms).
654+ // eslint-disable-next-line no-await-in-loop
655+ await new Promise ( resolve =>
656+ setTimeout ( resolve , attempt * 200 ) ,
657+ )
658+ }
659+ }
635660 }
636661
637- // Remove the "files" field so pnpm includes all files (including tests).
638- // Also remove unnecessary lifecycle scripts that could interfere with testing.
639- let editablePkgJson
640- try {
641- editablePkgJson = await readPackageJson ( pkgJsonPath , {
642- editable : true ,
643- } )
644- } catch ( parseError ) {
645- // If JSON parsing fails, read the file content to help diagnose the issue.
662+ if ( ! editablePkgJson ) {
663+ // All retries failed, add diagnostic info.
664+ const pkgJsonStats = await fs . stat ( pkgJsonPath )
646665 const fileContent = await fs . readFile ( pkgJsonPath , 'utf8' )
647666 throw new Error (
648- `Invalid package.json: ${ parseError . message } . File size: ${ pkgJsonStats . size } , Content preview: ${ fileContent . slice ( 0 , 200 ) } ` ,
667+ `Invalid package.json after 3 retries : ${ lastError . message } . File size: ${ pkgJsonStats . size } , Content preview: ${ fileContent . slice ( 0 , 200 ) } ` ,
649668 )
650669 }
651670 const { scripts } = editablePkgJson . content
0 commit comments