Skip to content

Troubleshooting

Common errors and their solutions when working with NDArray.

Installation Issues

"FFI extension not loaded"

Error:

Error: FFI extension is not loaded

Solution: Enable FFI in your php.ini:

ini
extension=ffi
ffi.enable=true

Or enable for specific scripts:

ini
ffi.enable=preload

"Cannot load Rust library"

Error:

RuntimeException: Failed to load Rust library

Solution:

  1. Check that the Rust library was compiled: cargo build --release
  2. Verify the library path in your configuration
  3. Check library dependencies with ldd (Linux) or otool -L (macOS)

Shape Errors

"Shape mismatch"

Error:

ShapeException: Shape mismatch for operation

Cause: Arrays have incompatible shapes for the operation.

Solution:

php
$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:

php
$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 5

Cause: Index exceeds array dimensions.

Solution:

php
$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 dimensions

Cause: More indices provided than array dimensions.

Solution:

php
$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:

php
$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 operation

Cause: Operation not supported for the array's data type.

Solution:

php
$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 index

Cause: Trying to assign an array to a single element position.

Solution:

php
$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 row

Memory Issues

"Out of memory"

Error:

RuntimeException: Failed to allocate memory

Cause: Trying to allocate an array larger than available memory.

Solution:

php
// 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:

php
$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:

  1. PHP Loops
php
// Bad: 1000 FFI calls
for ($i = 0; $i < 1000; $i++) {
    $sum += $arr[$i];
}

// Good: 1 FFI call
$sum = $arr->sum();
  1. Growing Arrays
php
// 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:

php
// 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];  // 0

Slicing Issues

"Only one ellipsis allowed"

Error:

IndexException: Only one ellipsis (...) allowed per slice

Cause: Used multiple ellipses in one slice.

Solution:

php
$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:

php
$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 unchanged

Debugging Tips

Enable Error Reporting

php
error_reporting(E_ALL);
ini_set('display_errors', '1');

Check Array Properties

php
$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

php
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

php
$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:

  1. Check the API Reference for correct method signatures
  2. Check your data types and shapes carefully
  3. Enable all error reporting to see full stack traces

See Also

Released under the MIT License.