Open andremorescocia opened 1 week ago
@andremorescocia can you provide a minimum reproducible case? This worked in version 3? Seems like yoga is hitting a limit. Nothing there changed recently
Hey @diegomura, I hope you're doing okay :) I will bump up this thread because I get the same RangeError. Please, find below more details. Massive thanks in advance for your help.
Im using latest 4.1.5
version of @react-pdf/renderer
. I tried to downgrade to lower versions, but nothing helped.
The error I get.
pdf.worker.ts:20 RangeError: Invalid array length
at Array.push (<anonymous>)
at y (yoga-wasm-base64-esm.js:63:248)
at 00047d12:0xd3fc
at 00047d12:0xb7e
at 00047d12:0x9b62
at 00047d12:0xa5a5
at 00047d12:0x5a9c
at 00047d12:0x769c
at 00047d12:0xc3cf
at 00047d12:0x76d7
The error above indicates an exceeding of limits with internal data structures in yoga - I assume.
It happens for super complex trees that I recursively render in PDF document - for less complex trees this render algo works very well as expected, enabling download. I am attaching a test tree.txt
file (JS object), that actually produces this error log.
*UPDATE (uploaded object with the proper structure, ready for processing) tree.txt
I'm implementing a PDF download in Next.js app 14.2.3
. The <ObjectItem/>
is the component that produces the following error. It accepts the treeData
through the props
which is the tree.txt
object I attached above.
Input data structure interface
that I iterate through.
export interface TransformedNode {
name: string;
object_id: string;
node_id?: string;
work_id: string;
object_type: string;
object_subtype?: string;
size: number;
error?: string;
total_size?: number;
number_of_objects?: number;
skipped_objects?: boolean;
all_infected_symbols?: string[];
infected_symbols?: string[];
infected?: boolean;
hashes: {
sha256: string;
[key: string]: any;
};
match_search?: boolean;
children?: TransformedNode[] | [];
ok?: {
object_metadata: {
name?: string;
format?: string;
natural_language?: string;
programming_language?: string;
nsfw_verdict?: string;
[key: string]: any;
};
[key: string]: any;
};
relation_metadata: {
name?: string;
[key: string]: any;
};
navigation_nodes?: NavigationNode[];
[key: string]: any;
}
Component code
import { View, Text } from '@react-pdf/renderer';
import { styles } from './ObjectItem.styles';
import { TransformedNode } from '@/app/(workspace)/analysis/_shared/types';
import { forbiddenObjectKeys } from '@/app/(workspace)/analysis/_shared/components/StackSection/AccordionItem';
import { globalPdfStyles } from '@/_shared/styles/globalPdfStyles';
interface ObjectItemProps {
treeData: TransformedNode;
}
const ObjectItem = ({ treeData }: ObjectItemProps): JSX.Element => {
const shouldRender = (value: any): boolean => {
if (value === null || value === '' || value === undefined) return false;
if (Array.isArray(value)) {
return value.some(item => shouldRender(item));
}
if (typeof value === 'object' && Object.keys(value).length === 0) return false;
return true;
};
const renderValue = (value: any, indentLevel: number): JSX.Element | string => {
if (Array.isArray(value)) {
return (
<View style={[styles.arrayWrapper, { marginLeft: indentLevel * 2 }]}>
{value.map((item, index) => (
<View wrap={false} key={index}>
{typeof item === 'object' ? (
<View style={[styles.objectWrapper, { marginLeft: (indentLevel + 1) * 2 }]}>
{Object.entries(item)
.filter(([nestedKey, nestedValue]) => shouldRender(nestedValue))
.map(([nestedKey, nestedValue]) => (
<View wrap={false} key={nestedKey} style={styles.objectField}>
<Text style={globalPdfStyles.boldText}>{nestedKey.replace(/_/g, ' ')}</Text>
{renderValue(nestedValue, indentLevel + 2)}
</View>
))}
</View>
) : (
<View wrap={false} style={styles.valueWrapper}>
<Text style={styles.value}>{item.toString()}</Text>
</View>
)}
</View>
))}
</View>
);
}
if (typeof value === 'object' && value !== null) {
return (
<View style={[styles.objectWrapper, { marginLeft: indentLevel * 2 }]}>
{Object.entries(value)
.filter(([nestedKey, nestedValue]) => shouldRender(nestedValue))
.map(([nestedKey, nestedValue]) => (
<View key={nestedKey} style={styles.objectField}>
<Text style={globalPdfStyles.boldText}>{nestedKey.replace(/_/g, ' ')}</Text>
{renderValue(nestedValue, indentLevel + 1)}
</View>
))}
</View>
);
}
//Known problem with word break NOT SUPPORTED. A workaround solution taken from -> https://github.com/diegomura/react-pdf/issues/248 e.g. to make long strings like sha... just word break
return (
<View wrap={false} style={styles.valueWrapper}>
<Text style={styles.value}>
{value
?.toString()
.split('')
.map((s: string, index: number) => {
return <Text key={index}>{s}</Text>;
}) || 'N/A'}
</Text>
</View>
);
};
const renderObject = (obj: TransformedNode, indentLevel: number): JSX.Element[] => {
return Object.entries(obj)
.filter(
([key, value]) => ![...forbiddenObjectKeys, 'children'].includes(key) && shouldRender(value)
)
.map(([key, value]) => (
<View key={key} style={[styles.objectField, { marginLeft: indentLevel * 2 }]}>
<Text style={[globalPdfStyles.boldText, { color: '#0053D8' }]}>
{key.replace(/_/g, ' ')}
</Text>
{renderValue(value, indentLevel + 1)}
</View>
));
};
return (
<View style={[styles.container]}>
<View style={[styles.wrapper]}>
<Text
id={`object-${treeData.node_id}`}
style={[globalPdfStyles.subHeading, { fontSize: 13 }]}
>
({treeData.node_id}) {treeData.object_type}{' '}
{treeData.object_subtype && `(${treeData.object_subtype})`}
</Text>
{renderObject(treeData, 0)}
</View>
{treeData.children?.map((child, index) => (
<ObjectItem key={`${child.object_id}-${index}`} treeData={child} />
))}
</View>
);
};
export default ObjectItem;
Additionally attaching styles.
import { StyleSheet } from '@react-pdf/renderer';
export const styles = StyleSheet.create({
container: {
padding: 5,
},
wrapper: {
marginBottom: 30,
},
objectField: {
marginBottom: 5,
},
valueWrapper: {
justifyContent: 'center',
marginLeft: 5,
padding: '3pt 10pt',
border: '1pt solid #e7e7e7',
borderRadius: 5,
},
value: {
fontSize: 9,
color: '#555',
},
arrayWrapper: {
marginTop: 5,
padding: 5,
rowGap: 3,
},
objectWrapper: {
marginTop: 5,
borderLeft: '1pt solid #e7e7e7',
padding: 5,
},
});
Feel free @diegomura to ask more questions, but tbh I don't know what else I should add here. Thanks!
Describe the bug Updating to Version 4.x results in Error:
RangeError: Invalid array length at Array.push ()
at y (yoga-wasm-base64-esm.js:1273:1)
at 00047d12:0xd3fc
at 00047d12:0xb7e
at 00047d12:0x9b62
at 00047d12:0xa5a5
at 00047d12:0x5a9c
at 00047d12:0x769c
at 00047d12:0xc3cf
at 00047d12:0x76d7
The error occurs when generating a PDF with a very large volume of data (array.length > 5000). Even after taking more than 3 minutes, it eventually causes the error.
We tested using manual pagination, such as chunks, by defining the number of items per page, and it worked in a time 10 times faster. However, this solution is not viable because we cannot fix the number of items per page, as each generated PDF contains fields with variable sizes.
Expected behavior It is expected that the error mentioned above does not occur and that the PDF generation has better performance using its native pagination functions.
Desktop (please complete the following information):