Troubleshooting
Common errors and their solutions when working with NDArray.
Installation Issues
"FFI extension not loaded"
Error:
Error: FFI extension is not loadedSolution: Enable FFI in your php.ini:
extension=ffi
ffi.enable=trueOr enable for specific scripts:
ffi.enable=preload"Cannot load Rust library"
Error:
RuntimeException: Failed to load Rust librarySolution:
- Check that the Rust library was compiled:
cargo build --release - Verify the library path in your configuration
- Check library dependencies with
ldd(Linux) orotool -L(macOS)
Shape Errors
"Shape mismatch"
Error:
ShapeException: Shape mismatch for operationCause: Arrays have incompatible shapes for the operation.
Solution:
$a = NDArray::zeros([3, 4]);
$b = NDArray::zeros([5, 4]);
// Check shapes before operations
echo implode(',', $a->shape()); // 3,4
echo implode(',', $b->shape()); // 5,4
// Make compatible
if ($a->shape() !== $b->shape()) {
// Reshape, broadcast, or fix the data
}"Cannot broadcast"
Error:
ShapeException: Cannot broadcast shapes [3,4] and [5]Cause: Arrays cannot be broadcast to a common shape.
Solution:
$a = NDArray::zeros([3, 4]);
$b = NDArray::zeros([4]); // Works: [3,4] + [4] → [3,4]
// Check broadcasting rules
$c = NDArray::zeros([5]); // Won't work with [3,4]Index Errors
"Index out of bounds"
Error:
IndexException: Index 10 is out of bounds for dimension 0 with size 5Cause: Index exceeds array dimensions.
Solution:
$arr = NDArray::zeros([5]);
// Check bounds before accessing
$index = 10;
if ($index >= 0 && $index < $arr->shape()[0]) {
$value = $arr[$index];
}
// Or use negative indexing
$last = $arr[-1]; // Valid: gets last element"Too many indices"
Error:
IndexException: Too many indices: got 3 for array with 2 dimensionsCause: More indices provided than array dimensions.
Solution:
$matrix = NDArray::zeros([3, 4]);
// 2D array needs exactly 2 indices for scalar access
$value = $matrix->get(1, 2); // Correct
// For partial indexing, use fewer indices
$row = $matrix->get(1); // Returns 1D view"Invalid slice selector"
Error:
IndexException: Invalid slice selector: 'abc'Cause: Slice syntax is invalid.
Solution:
$arr = NDArray::arange(10);
// Valid slice syntax
$slice = $arr->slice(['2:5']); // Range
$slice = $arr->slice(['::2']); // With step
// Note: Negative step (e.g., '::-1') is not supported
// Use $arr->flip() to reverse arrays
// Invalid: $arr->slice(['abc']);Type Errors
"Invalid dtype"
Error:
InvalidArgumentException: Invalid dtype for operationCause: Operation not supported for the array's data type.
Solution:
$arr = NDArray::array([1, 2, 3], DType::Int32);
// Check dtype
echo $arr->dtype()->name; // "Int32"
// Convert if needed
$float_arr = $arr->astype(DType::Float64);"Cannot assign array to scalar index"
Error:
IndexException: Cannot assign array to scalar indexCause: Trying to assign an array to a single element position.
Solution:
$arr = NDArray::zeros([3, 3]);
// Correct: Assign scalar to scalar index
$arr->set([0, 0], 5);
// Correct: Assign array to slice
$row = NDArray::array([1, 2, 3]);
$arr[0] = $row; // Assign to rowMemory Issues
"Out of memory"
Error:
RuntimeException: Failed to allocate memoryCause: Trying to allocate an array larger than available memory.
Solution:
// Check memory first
$shape = [100000, 100000]; // 74.5 GB for Float64!
$bytes = array_product($shape) * 8;
$gb = $bytes / (1024 * 1024 * 1024);
if ($gb > 8) { // More than 8 GB
// Process in batches
processInBatches($shape);
}High Memory Usage
Symptom: Script uses more memory than expected.
Cause: Creating unnecessary copies instead of views.
Solution:
$data = NDArray::random([10000, 10000]);
// Bad: Creates copy
$subset = $data->slice(['0:1000'])->copy(); // 80 MB copied
// Good: Uses view
$subset = $data->slice(['0:1000']); // 0 bytes copied
// Good: Explicit cleanup when done
unset($large_array);Performance Issues
Operations are slow
Symptom: Simple operations take seconds.
Common Causes:
- PHP Loops
// Bad: 1000 FFI calls
for ($i = 0; $i < 1000; $i++) {
$sum += $arr[$i];
}
// Good: 1 FFI call
$sum = $arr->sum();- Growing Arrays
// Bad: O(n²) array creation
$result = NDArray::array([]);
for ($i = 0; $i < 1000; $i++) {
$result = NDArray::concatenate([$result, NDArray::array([$i])]);
}
// Good: Pre-allocate
$result = NDArray::zeros([1000]);
for ($i = 0; $i < 1000; $i++) {
$result[$i] = $i;
}Undefined values from empty()
Symptom: empty() array contains unexpected values.
Cause: NDArray::empty() creates uninitialized memory.
Solution:
// empty() values are undefined - must fill before reading
$arr = NDArray::empty([10]);
echo $arr[0]; // Undefined value!
// Use zeros() for initialized memory
$arr = NDArray::zeros([10]);
echo $arr[0]; // 0Slicing Issues
"Only one ellipsis allowed"
Error:
IndexException: Only one ellipsis (...) allowed per sliceCause: Used multiple ellipses in one slice.
Solution:
$arr = NDArray::zeros([2, 3, 4, 5]);
// Valid: One ellipsis
$slice = $arr->slice([0, '...']);
// Invalid: Multiple ellipses
// $slice = $arr->slice(['...', 0, '...']);Slice modifies original
Symptom: Changing a slice changes the original array.
Explanation: Slices are views - they share memory with the original.
Solution:
$original = NDArray::zeros([5, 5]);
$slice = $original->slice(['0:2', '0:2']);
// This modifies both slice AND original
$slice->assign(1);
// Make a copy if you need independence
$independent = $original->slice(['0:2', '0:2'])->copy();
$independent->assign(2); // Original unchangedDebugging Tips
Enable Error Reporting
error_reporting(E_ALL);
ini_set('display_errors', '1');Check Array Properties
$arr = NDArray::random([10, 20]);
echo "Shape: " . implode(',', $arr->shape()) . "\n";
echo "NDim: " . $arr->ndim() . "\n";
echo "Size: " . $arr->size() . "\n";
echo "DType: " . $arr->dtype()->name . "\n";
echo "Is View: " . ($arr->isView() ? 'Yes' : 'No') . "\n";
echo "Contiguous: " . ($arr->isContiguous() ? 'Yes' : 'No') . "\n";Validate Before Operations
function safeAdd(NDArray $a, NDArray $b): NDArray {
if ($a->shape() !== $b->shape()) {
throw new InvalidArgumentException(
"Shape mismatch: [" . implode(',', $a->shape()) .
"] vs [" . implode(',', $b->shape()) . "]"
);
}
return $a->add($b);
}Profile Memory Usage
$startMemory = memory_get_usage(true);
$arr = NDArray::random([1000, 1000]);
$endMemory = memory_get_usage(true);
$usedMB = ($endMemory - $startMemory) / (1024 * 1024);
echo "Memory used: {$usedMB} MB\n";Getting Help
If you encounter an issue not covered here:
- Check the API Reference for correct method signatures
- Check your data types and shapes carefully
- Enable all error reporting to see full stack traces
See Also
- FFI Internals - Understanding the PHP-Rust bridge
- Performance Best Practices - Writing efficient code
- Views vs Copies - Memory management
