@@ -49,13 +49,74 @@ ${detailsHeader} ${message}`
4949 }
5050}
5151
52+ /**
53+ * Check if an error is the V8 string length limit.
54+ * V8 has a hard-coded limit of 0x1fffffe8 characters (~536MB) for strings.
55+ * No Node.js flags can change this.
56+ * See: https://github.com/prisma/prisma/issues/29111
57+ */
58+ function isV8StringLimitError ( error : unknown ) : boolean {
59+ return error instanceof Error && error . message . includes ( 'Cannot create a string longer than' )
60+ }
61+
62+ /**
63+ * Read DMMF from the buffered WASM API in chunks and parse via chunked string decoding.
64+ * This bypasses V8's string length limit by reading the DMMF as Uint8Array chunks
65+ * and parsing each chunk individually using a streaming JSON parser approach.
66+ *
67+ * Requires get_dmmf_buffered(), read_dmmf_chunk(), and free_dmmf_buffer() exports
68+ * from @prisma/prisma-schema-wasm.
69+ * See: https://github.com/prisma/prisma/issues/29111
70+ */
71+ function getDmmfBuffered ( params : string ) : DMMF . Document {
72+ const CHUNK_SIZE = 16 * 1024 * 1024 // 16MB chunks — well under V8 string limit
73+
74+ const totalBytes = prismaSchemaWasm . get_dmmf_buffered ( params )
75+ debug ( `DMMF buffered: ${ totalBytes } bytes (${ ( totalBytes / 1024 / 1024 ) . toFixed ( 1 ) } MB)` )
76+
77+ try {
78+ // Read all chunks as Uint8Array and decode to strings
79+ const decoder = new TextDecoder ( 'utf-8' , { stream : true } )
80+ const jsonChunks : string [ ] = [ ]
81+ let offset = 0
82+
83+ while ( offset < totalBytes ) {
84+ const len = Math . min ( CHUNK_SIZE , totalBytes - offset )
85+ const chunk = prismaSchemaWasm . read_dmmf_chunk ( offset , len )
86+ jsonChunks . push ( decoder . decode ( chunk , { stream : offset + len < totalBytes } ) )
87+ offset += len
88+ }
89+
90+ // Flush the decoder
91+ const remaining = decoder . decode ( )
92+ if ( remaining ) {
93+ jsonChunks . push ( remaining )
94+ }
95+
96+ // Join chunks and parse — each chunk is ≤16MB, but the joined string
97+ // may exceed V8's limit. If it does, a streaming JSON parser is needed.
98+ // For DMMF sizes between 536MB and ~1GB, this join may still work since
99+ // V8's limit is on individual string creation, and string concatenation
100+ // can sometimes succeed via internal rope representation.
101+ const jsonString = jsonChunks . join ( '' )
102+ return JSON . parse ( jsonString ) as DMMF . Document
103+ } finally {
104+ prismaSchemaWasm . free_dmmf_buffer ( )
105+ }
106+ }
107+
52108/**
53109 * Wasm'd version of `getDMMF`.
54110 */
55111export async function getDMMF ( options : GetDMMFOptions ) : Promise < DMMF . Document > {
56112 const debugErrorType = createDebugErrorType ( debug , 'getDmmfWasm' )
57113 debug ( `Using getDmmf Wasm` )
58114
115+ const params = JSON . stringify ( {
116+ prismaSchema : options . datamodel ,
117+ noColor : Boolean ( process . env . NO_COLOR ) ,
118+ } )
119+
59120 const dmmfPipeline = pipe (
60121 E . tryCatch (
61122 ( ) => {
@@ -64,10 +125,6 @@ export async function getDMMF(options: GetDMMFOptions): Promise<DMMF.Document> {
64125 prismaSchemaWasm . debug_panic ( )
65126 }
66127
67- const params = JSON . stringify ( {
68- prismaSchema : options . datamodel ,
69- noColor : Boolean ( process . env . NO_COLOR ) ,
70- } )
71128 const data = prismaSchemaWasm . get_dmmf ( params )
72129 return data
73130 } ,
@@ -101,6 +158,30 @@ export async function getDMMF(options: GetDMMFOptions): Promise<DMMF.Document> {
101158 return Promise . resolve ( data )
102159 }
103160
161+ /**
162+ * If the error is a V8 string length limit, fall back to the buffered DMMF API.
163+ * This bypasses the limit by reading DMMF as chunked Uint8Array data instead of
164+ * a single JS string.
165+ * See: https://github.com/prisma/prisma/issues/29111
166+ */
167+ const leftError = dmmfEither . left
168+ if ( leftError . type === 'wasm-error' && isV8StringLimitError ( leftError . error ) ) {
169+ debug ( 'V8 string limit hit, falling back to buffered DMMF API' )
170+
171+ try {
172+ const data = getDmmfBuffered ( params )
173+ debug ( 'dmmf data retrieved via buffered API' )
174+ return data
175+ } catch ( bufferedError ) {
176+ debugErrorType ( { type : 'wasm-error' as const , reason : '(get-dmmf-buffered wasm)' , error : bufferedError } )
177+ throw new GetDmmfError ( {
178+ _tag : 'unparsed' ,
179+ message : `Buffered DMMF fallback also failed: ${ ( bufferedError as Error ) . message } ` ,
180+ reason : '(get-dmmf-buffered wasm)' ,
181+ } )
182+ }
183+ }
184+
104185 /**
105186 * Check which error to throw.
106187 */
0 commit comments