You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MLX Array API compatibility: upstream status, compatibility #450
Use this issue an umrella issue, open individual issues for groups of tests from the test suite, edit the links into this top post into the list above. (If you cannot edit it, ping @ev-br)
Problems/failures with individual functions, as uncovered by the test suite: discuss in the sub-issues. Keep this one for general blockers.
Known blockers
missing __array_namespace_info__ : would be best to submit a PR upstream
missing .device attribute of the array object : nothing to do about it
array-api-compat: Atleast __array_namespace_info__() is required as per standard which is not available in MLX. This has to be the first step addition to the compat library.
Most of the test failures are because MLX has no __complex__ method on its array type, so every attempt to pull a Python complex scalar out of a complex-dtype MLX array falls back to trying __float__ instead (that's standard CPython behavior for the complex() constructor, not a bug in the test) and blows up.
Some of these failures, I believe, are also a fix in the array-api-tests itself. I tried changing complex(x) -> complex(float(xp.real(x)), float(xp.imag(x))) in some places and now we are left with 415 failures (all of the complex failures were not removed. It might make sense for MLX to xfail these but not sure yet!)
I also found a seg fault in this process (discovered via hypothesis):
import mlx.core as mlx
x = mlx.zeros(())
mlx.expand_dims(x, axis=(-3, -2))
Gives:
[1] 87881 segmentation fault
Reporting this to mlx. The test suite is already uncovering bugs in mlx!
I'll continue to keep adding more info to this report.
Edit: Just saw ml-explore/mlx#3984, might help solve the complex issue mentioned above.
Hi, I think it would be better to instead of running all the tests together make sub-issues for different categories for easier tracking
Hi, sorry, I don't understand. The above table has some categories. I haven't really worked on any failures yet, just pointed some out. The fix that I suggested was just to unblock the test suite and the ones that were bugs in MLX itself.
All the complex failures are gone now after the upstream PR merge in MLX! That means all the
float() argument must be a string or a real number, not 'complex'
errors are gone. Thanks for the effort @aaishwarymishra! Which means now we have
289 failed, 1146 passed
Hypothesis found another bug in MLX.
importmlx.coreasmxa=mx.zeros((0, 0))
r=mx.linalg.cholesky(a)
mx.eval(r) # process aborts here
Output:
** On entry to POTRF, parameter number 4 had an illegal value
libc++abi: terminating due to uncaught exception of type std::runtime_error: [Cholesky::eval_cpu] Cholesky decomposition failed with error code -4
[1] 31154 abort
Reporting it too.
@ev-br Should we add __array_namespace_info__() in compat? Currently, I run the tests by:
ifnothasattr(xp, "__array_namespace_info__"):
pytest.skip(
"__array_namespace_info__ is not defined in the array module",
allow_module_level=True,
)
Thanks for pointing out failure categories!
My suggestion is to work through them in passes: you did the first pass, with categories, great. Next pass is to list individual failures per group of functions, in a style similar to #452, preferably with reproducible examples that the test suite emits. Then we can quickly triage them. And then for those which are easy-fix in MLX, send PRs to MLX. Observing @aaishwarymishra 's recent MLX PRs, it looks like they are receptive to PRs and are ready to merge them quickly. Opening issues upstream not sure, especially for small items like empty(0) or cholesky((0,0)).
Should we add __array_namespace_info__() in compat?
If it helps working through unrelated items, yes why not. We won't merge MLX compat PRs not yet, so you could work off a -compat branch with __array_namespace_info__() if that makes it easier.
Would be great to continue filling in missing MWEs.
Some of these items, esp creation functions, are being worked on in #452
Quick triage:
leave out things with data-dependent shapes (nonzero, unique_all etc)
leave out device-related issues
special cases for numerical functions (infs nans and such): we maintain lists of xfails for these for essentially all wrapped libraries, so can leave to the end
several items look uncontroversial and free from backwards compatible considerations (__pos__, __index__, mT, hypot, empty inputs). Are you up to sending upstream PRs for these and related omissions? Would be best to coordinate with @aaishwarymishra
simple signature tweaks, like renaming/permuting arguments can be done in the compat layer
missing axis arguments: I actually wonder what it takes to implement it in MLX.
some of the listed "signature mismatch" I'm not sure about. Take broadcast_to as an example. What is the mismatch? The MLX signature looks to be a proper superset of the Array API signature, modulo tuple vs sequence annotation (which can be ignored IMO):
Also, with a workaround, I'm able to fix this by adding a condition in the test suite, and we are down to just 240 failures! All the axis not found and a few other function signature complaints are just inconsistencies.
The workaround (kuddos to Claude Code, I haven't tested it too well):
def_is_uninformative_signature(sig: Signature) ->bool:
# Some Python versions (e.g. 3.14) don't raise ValueError for callables# backed by extension modules (e.g. nanobind, pybind11) that lack a# parseable text signature. Instead inspect.signature() falls back to a# generic "(*args, **kwargs)" signature which carries no real parameter# information, so we treat it the same as an uninspectable signature.params=list(sig.parameters.values())
returnlen(params) ==2and [p.kindforpinparams] == [
Parameter.VAR_POSITIONAL,
Parameter.VAR_KEYWORD,
]
Maybe. At the moment though, there seem to be too many moving parts: array-api-tests, mlx, nanobind and inspect.signature. It's really not yet clear where the problem is, not to me at least.
It'd be best to move the two first items out of the equation: cook up a dummy nanobind-wrapped module and see if the inspect problem reproduces in the same python version dependent way. If it does, there's still a question whether it's in inspect or in nanobind, but at least we know it's upstream not us.
Let's take a step back, sorry I should have asked this earlier. What is the expected behavior and what is the actual behavior we are seeing? Is it that some signatures were not parseable with inspect.signature in older versions of python/nanobind, and are parseable with newer versions? If so, that's an improvement. Or is it the other way around, some signatures were parseable on old versions and newer versions only give a generic <Signature (*args, **kwargs)>?
Next, what is the extent of the problem: is it throwing off some tests (test_signatures, what else?) or only the generation of the compatibility overview table, #450 (comment) ?
If the latter, maybe we could use the __nb_signature__ attribute instead of inspect?
I think it would be cleaner to make sub issue for each section for better tracking so we don't pollute the main issue and this can be be used as the parent tracker.
Is that table above really the status? I thought MLX was much closer to completeness; I just checked a couple of common functions: moveaxis does exist, and argsort and stack do have an axis keyword.
Also agreed with @ev-br's about no device= keyword) - that's a single issue, it just touches many functions.
The table above, I think, is slightly off indeed. Quick check; moveaxis complaint about incompatible signature just hides an edge case with empty inputs:
In [1]: import mlx.core as mx
In [2]: mx.moveaxis(mx.asarray([], dtype=bool), (), ())
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[2], line 1
----> 1 mx.moveaxis(mx.asarray([], dtype=bool), (), ())
TypeError: asarray(): incompatible function arguments. The following argument types are supported:
1. asarray(a: Union[scalar, array, Sequence, DLPackCompatible], dtype: Optional[Dtype] = None, *, copy: Optional[bool] = None) -> array
Invoked with types: list, kwargs = { dtype: type }
Whether there are other problems is a bit hard to tell because this edge case chokes the test suite. One other thing that gets in the way of the test suite is the lack of __complex__, fixed in ml-explore/mlx#3984.
So I suppose it'd be best to re-generate the table with the built-from-source mlx.
What is the expected behavior and what is the actual behavior we are seeing?
Here's the thing: In older CPython versions, the inspect module for custom callables simply raised a ValueError. This is also what our test suite expects, and once a ValueError is raised, it goes to _test_uninspectable_func(stub.__name__, func, stub_sig).
The newer versions of CPython, instead of raising a ValueError, it gives a generic signature as you mentioned <Signature (*args, **kwargs)> this case is not handled by array-api-tests and simply gives Argument 'X' missing from signature. A simple condition like the one mentioned above should be enough to fix this. Let me put before after here for easy comparison:
(If signature contains *args, **kwargs, return sig = None and again follow the same patter as before)
The pass and fail for different versions in CI should mostly be because of how CPython shipped this feature; all the latest ones have it anyway. This fix works for all the versions. (I think this is the PR in CPython that adds this feature.)
Edit: My stupid laptop hung midway, continuing from above
With that said, I do need to update the table since there have been more fixes to the upstream MLX and some fixes in my local array-api-tests module. So the table above is quite inaccurate.
Here's the thing: In older CPython versions, the inspect module for custom callables simply raised a ValueError. This is also what our test suite expects, and once a ValueError is raised
Okay, so this is something specific to test_signatures. I'm still not 100% sure what is the user visible effect here (where "user" is the person running the test suite), but anyhow let's take it to a issue or even a PR to array-api-tests.
With some manual effort and comparing function signatures from the docs, I have these findings. I'll check for exact edge cases later.
Next goal is to make a similar list for extensions.
These functions with missing parameters cause 27 failures:
arrange: (edge case?)
diff: missing prepend, append
linespace: missing endpoint
astype: missing copy
take_along_axis: (edge case probably)
pinv: no rtol
moveaxis: (edge case)
reshape: no copy
clip: (edge case maybe)
arctan2: (may be an edge case)
cumsum: include_initial missing
cumprod: include_initial missing
prod: missing dtype missingg
std: correction parameter
sum: dtype
var: correction parameter
permute_dims: (edge case?)
argsort: descending, stable missing
sort: descending, stable missing
qr: mode missing
svd: full_matrices parameter (mlx has compute_uv instead — different semantics)
@ev-br
Small question. How is it decided what goes in the compat layer and what in the upstream library? For example the __array_namespace_info__, some libraries have it some have it in compat layer. A few parameters like device would be a bit more complicated, so it makes sense (at least temporarily) to have them in compat (like CuPy).
Ideally, the compat layer is ephemeral and goes away at some point. And MLX seems receptive to PRs, so---again ideally---the endgame for MLX is similar to JAX today: there is no compatibility layer, everything lives in MLX itself, and those things where it deviates from the standard (JAX: __setitem__, data-dependent shapes, MLX: devices, data-dependent shapes) are clearly marked / skipped upstream/
The xfails file will have ~250 entries, of which ~100 are "low-prio" special cases. The remaining ones are also repeated: a missing function causes at least two failures; the missing __index__ causes a half dozen etc.
With that, we could ask MLX maintainers if they prefer issues for individual failures, or PRs, or something else entirely.
Since array-api-tests now supports multiple xfail files, it would make sense to have them for different builds. Some build-dependent failures were discovered here; there might be a few more.
I'm not sure if we have found any platform-dependent failures yet.
Activity
prady0t commentedon Aug 5, 2026
Adding more info to this tracker:
array-api-compat: Atleast__array_namespace_info__()is required as per standard which is not available in MLX. This has to be the first step addition to the compat library.array-api-tests: Changes needed (which are also needed for us to be able to at least run the test suite with MLX) are mentioned in this comment: None dtype comparison not supported in MLX array-api-tests#447 (comment), and the PR: None dtype comparison not supported in MLX array-api-tests#447 itself needs to be addressed.With that said, running the test suite right now (skipping array_namespace_info and adding rest of the changes) looks something like this :
As suggested by @ev-br, trying to find a breadth-first summary of the failures (and this is from AI):
TypeError: float() argument must be a string or a real number, not 'complex'AssertionError: ... is not defined/module has no attribute)Argument 'axis' missing, wrong parameter names, etc.)TypeError: incompatible function arguments__index__,__complex__,device,mT,to_device)__array_namespace_info__)iinfo.bits, etc.)Hypothesis found 2 distinct failuresMost of the test failures are because MLX has no
__complex__method on its array type, so every attempt to pull a Python complex scalar out of a complex-dtype MLX array falls back to trying__float__instead (that's standard CPython behavior for the complex() constructor, not a bug in the test) and blows up.Some of these failures, I believe, are also a fix in the
array-api-testsitself. I tried changingcomplex(x)->complex(float(xp.real(x)), float(xp.imag(x)))in some places and now we are left with 415 failures (all of the complex failures were not removed. It might make sense for MLX to xfail these but not sure yet!)I also found a seg fault in this process (discovered via hypothesis):
Gives:
Reporting this to mlx. The test suite is already uncovering bugs in mlx!
I'll continue to keep adding more info to this report.
Edit: Just saw ml-explore/mlx#3984, might help solve the
complexissue mentioned above.aaishwarymishra commentedon Aug 5, 2026
Hi, I think it would be better to instead of running all the tests together make sub-issues for different categories for easier tracking :)
prady0t commentedon Aug 6, 2026
Hi, sorry, I don't understand. The above table has some categories. I haven't really worked on any failures yet, just pointed some out. The fix that I suggested was just to unblock the test suite and the ones that were bugs in MLX itself.
All the
complexfailures are gone now after the upstream PR merge in MLX! That means all theerrors are gone. Thanks for the effort @aaishwarymishra! Which means now we have
Hypothesis found another bug in MLX.
Output:
Reporting it too.
@ev-br Should we add
__array_namespace_info__()in compat? Currently, I run the tests by:ev-br commentedon Aug 6, 2026
Thanks for pointing out failure categories!
My suggestion is to work through them in passes: you did the first pass, with categories, great. Next pass is to list individual failures per group of functions, in a style similar to #452, preferably with reproducible examples that the test suite emits. Then we can quickly triage them. And then for those which are easy-fix in MLX, send PRs to MLX. Observing @aaishwarymishra 's recent MLX PRs, it looks like they are receptive to PRs and are ready to merge them quickly. Opening issues upstream not sure, especially for small items like
empty(0)orcholesky((0,0)).ev-br commentedon Aug 6, 2026
If it helps working through unrelated items, yes why not. We won't merge MLX compat PRs not yet, so you could work off a -compat branch with
__array_namespace_info__()if that makes it easier.prady0t commentedon Aug 6, 2026
Makes sense. Thanks for the suggestion. Here's a tracker for all failing functions along with their failures. I'll add more to this table.
__getitem____setitem____index__mx.asarray(1).__index__()__pos__+mx.asarray(1)to_devicedevicemx.asarray(1).devicemTmx.ones((2,2)).mT__array_namespace__api_versionparameter__array_namespace_info__mx.__array_namespace_info__()__dlpack__streamparameterarangeasarrayemptyempty_likedtypeeyekparameterfullfull_likefill_valuelinspacenummeshgridlistinstead oftupletype(mx.meshgrid(mx.arange(3)))onesones_likedtypezeroszeros_likedtypeastypebroadcast_arrayslistinstead oftuplebroadcast_shapesmx.broadcast_shapes()can_castfinfoiinfobitsattributemx.iinfo(mx.int32).bitsresult_typefrom_dlpackfft,ifft,fftn,ifftn,rfft,irfft,rfftn,irfftnhfft,ihfftmx.fft.hfft(...)fftfreq,rfftfreqdparameter / behaviorfftshift,ifftshiftaxesparametertake_along_axisexpand_dimsmx.expand_dims(mx.zeros(()), axis=(-3, -2))moveaxisdestinationrepeatreshapeunstackbroadcast_toconcataxisdiffaxisflipaxispermute_dimsrollsqueezestackaxischoleskyupper; aborts on empty(0,0)mx.linalg.cholesky(mx.zeros((0,0)))crossaxisdetdiagonalmx.linalg.diagonal(...)eigeigheigvalshinvmatmulmatrix_normmx.linalg.matrix_norm(mx.eye(3))matrix_powermx.linalg.matrix_power(mx.eye(2), 2)matrix_rankmx.linalg.matrix_rank(mx.eye(3))matrix_transposeoutermx.linalg.outer(...)pinvrtol/ behavioral failuresqrmode/ behavioral failuresslogdetsolvesvdfull_matrices/ behavioral failuressvdvalsmx.linalg.svdvals(...)tensordotmx.linalg.tensordot(...)tracemx.linalg.trace(...)vecdotmx.linalg.vecdot(...)vector_normmx.linalg.vector_norm(...)argmaxargmincount_nonzeroaxisnonzeromx.nonzero(...)searchsortedmx.searchsorted(...)argsortaxis; behavioral failuressortaxis; behavioral failuresisinmx.isin(...)unique_allunique_countsunique_inverseunique_valuesall,any,max,mean,min,prod,std,sum,var,cumulative_sum,cumulative_prodaxisparameter and/or behavioral failuresacos,acosh,asin,asinh,cos,sin,tanhatan2bitwise_left_shift,bitwise_right_shift,bitwise_xorclipcopysignmx.copysign(...)expm1floor_dividehypotmx.hypot(...)nextaftermx.nextafter(...)remaindersignsignbitmx.signbit(...)ev-br commentedon Aug 6, 2026
Thanks, this is very helpful.
Would be great to continue filling in missing MWEs.
Some of these items, esp creation functions, are being worked on in #452
Quick triage:
device-related issues__pos__,__index__,mT,hypot, empty inputs). Are you up to sending upstream PRs for these and related omissions? Would be best to coordinate with @aaishwarymishraaxisarguments: I actually wonder what it takes to implement it in MLX.broadcast_toas an example. What is the mismatch? The MLX signature looks to be a proper superset of the Array API signature, modulotuplevssequenceannotation (which can be ignored IMO):ev-br commentedon Aug 7, 2026
Re missing axis argument in reductions: the docs list it, at least for some of them, eg. https://ml-explore.github.io/mlx/build/html/python/_autosummary/mlx.core.any.html#mlx.core.any
Is this version-dependent, or are there some behaviour differences that the test suite catches?
prady0t commentedon Aug 7, 2026
This has to be a Python version-specific issue. I ran the tests till now on Python 3.14 (inside a conda environment), and it failed for function signatures even though they were present in the nanobind C-extension function (nb::sig): https://github.com/ml-explore/mlx/blob/8056817bd1202477b6bed2b1f871da5960d64b28/python/src/ops.cpp#L1086
This kind of function signature is handled here:
https://github.com/data-apis/array-api-tests/blob/4b42cafee2e6a119e51a7178215aaba63e4663e9/array_api_tests/test_signatures.py#L265
And they are expected to raise a ValueError.
Here's the catch: on my local machines, Python 3.12.2 (from python.org), it passes. Some chance is,
inspect.signaturehandling has been relaxed? I'm not sure, and I need to investigate it a bit more. Here's the CPython section that might be handling this: https://github.com/python/cpython/blob/115400b5090f14233b72b255e483b4485c868100/Lib/inspect.py#L2436Should I raise an issue in CPython?
Also, with a workaround, I'm able to fix this by adding a condition in the test suite, and we are down to just
240 failures! All theaxisnot found and a few other function signature complaints are just inconsistencies.The workaround (kuddos to Claude Code, I haven't tested it too well):
ev-br commentedon Aug 8, 2026
Maybe. At the moment though, there seem to be too many moving parts:
array-api-tests,mlx,nanobindandinspect.signature. It's really not yet clear where the problem is, not to me at least.It'd be best to move the two first items out of the equation: cook up a dummy nanobind-wrapped module and see if the
inspectproblem reproduces in the same python version dependent way. If it does, there's still a question whether it's ininspector innanobind, but at least we know it's upstream not us.prady0t commentedon Aug 8, 2026
I don't think it's a nanobind issue. I created a minimal example and ran it on different versions of nanobind and Python in CI. See.
The results are consistent with nanobind v2.0.0 (2 years old), v2.13.0 (what mlx currently pins) and the latest.
It fails for these Python versions starting from 3.11.0 (The failure here means not raising the ValueError that our test suite expects):
3.11.9
3.11.13
3.12.3
3.12.10
3.13.0
3.13.9
3.14.0
Passes for:
3.11.0
3.11.8
3.12.0
3.12.2
ev-br commentedon Aug 9, 2026
Let's take a step back, sorry I should have asked this earlier. What is the expected behavior and what is the actual behavior we are seeing? Is it that some signatures were not parseable with
inspect.signaturein older versions of python/nanobind, and are parseable with newer versions? If so, that's an improvement. Or is it the other way around, some signatures were parseable on old versions and newer versions only give a generic<Signature (*args, **kwargs)>?Next, what is the extent of the problem: is it throwing off some tests (test_signatures, what else?) or only the generation of the compatibility overview table, #450 (comment) ?
If the latter, maybe we could use the
__nb_signature__attribute instead ofinspect?aaishwarymishra commentedon Aug 10, 2026
I think it would be cleaner to make sub issue for each section for better tracking so we don't pollute the main issue and this can be be used as the parent tracker.
rgommers commentedon Aug 10, 2026
Is that table above really the status? I thought MLX was much closer to completeness; I just checked a couple of common functions: moveaxis does exist, and argsort and stack do have an
axiskeyword.Also agreed with @ev-br's about no
device=keyword) - that's a single issue, it just touches many functions.ev-br commentedon Aug 10, 2026
The table above, I think, is slightly off indeed. Quick check;
moveaxiscomplaint about incompatible signature just hides an edge case with empty inputs:Whether there are other problems is a bit hard to tell because this edge case chokes the test suite. One other thing that gets in the way of the test suite is the lack of
__complex__, fixed in ml-explore/mlx#3984.So I suppose it'd be best to re-generate the table with the built-from-source
mlx.prady0t commentedon Aug 10, 2026
Here's the thing: In older CPython versions, the inspect module for custom callables simply raised a ValueError. This is also what our test suite expects, and once a ValueError is raised, it goes to
_test_uninspectable_func(stub.__name__, func, stub_sig).The newer versions of CPython, instead of raising a ValueError, it gives a generic signature as you mentioned
<Signature (*args, **kwargs)>this case is not handled byarray-api-testsand simply givesArgument 'X' missing from signature. A simple condition like the one mentioned above should be enough to fix this. Let me put before after here for easy comparison:Before:
After:
(If signature contains *args, **kwargs, return sig = None and again follow the same patter as before)
The pass and fail for different versions in CI should mostly be because of how CPython shipped this feature; all the latest ones have it anyway. This fix works for all the versions. (I think this is the PR in CPython that adds this feature.)
Edit: My stupid laptop hung midway, continuing from above
With that said, I do need to update the table since there have been more fixes to the upstream MLX and some fixes in my local
array-api-testsmodule. So the table above is quite inaccurate.prady0t commentedon Aug 10, 2026
With all error logs now and the triage recommendations from @ev-br (mentioned above), this is the newly generated table.
__getitem____setitem____index__mx.asarray(1).__index__()__pos__+mx.asarray(1)to_devicedevicemTmx.ones((2,2)).mT__array_namespace_info__mx.__array_namespace_info__()arangeasarraycopy=Falsesemantics incompatibleempty_likefullfull_likelinspacemeshgridlistinstead oftupletype(mx.meshgrid(mx.arange(3)))ones_likezeros_likeastypebroadcast_arrayslistinstead oftuplebroadcast_shapesmx.broadcast_shapes()can_castfinfoiinfobitsattributemx.iinfo(mx.int32).bitsresult_typefrom_dlpackrfft,rfftnhfft,ihfftmx.fft.hfft(...)fftfreq,rfftfreqtake_along_axisexpand_dimsmx.expand_dims(mx.zeros(()), axis=(-3, -2))moveaxisrepeatreshapeunstackpermute_dimscrossaxishandlingcholeskydetdiagonalmx.linalg.diagonal(...)eigeigvalseigheigvalshinvlinalg.matmulmx.linalg.matmul(...)matmulmatrix_normmx.linalg.matrix_norm(...)matrix_powermx.linalg.matrix_power(...)matrix_rankmx.linalg.matrix_rank(...)matrix_transposeoutermx.linalg.outer(...)pinvqrslogdetsolvesvdsvdvalsmx.linalg.svdvals(...)tensordotmx.linalg.tensordot(...)tracemx.linalg.trace(...)vecdotmx.linalg.vecdot(...)vector_normmx.linalg.vector_norm(...)argmaxuint32)argminuint32)nonzerosearchsortedmx.searchsorted(...)argsortsortisinunique_allunique_countsunique_inverseunique_valuescumulative_sumcumulative_prodprodsumstdvaracosacoshasinasinhcossintanhatan2bitwise_left_shiftbitwise_right_shiftbitwise_xorclipcopysignmx.copysign(...)expm1floor_dividehypotmx.hypot(...)nextaftermx.nextafter(...)remaindersignsignbitmx.signbit(...)prady0t commentedon Aug 10, 2026
Still need to check for edge cases
ev-br commentedon Aug 11, 2026
Okay, so this is something specific to
test_signatures. I'm still not 100% sure what is the user visible effect here (where "user" is the person running the test suite), but anyhow let's take it to a issue or even a PR toarray-api-tests.prady0t commentedon Aug 11, 2026
Sure. Let's brainstorm a little more on this in a separate issue thread.
prady0t commentedon Aug 11, 2026
With some manual effort and comparing function signatures from the docs, I have these findings. I'll check for exact edge cases later.
Next goal is to make a similar list for extensions.
These functions with missing parameters cause 27 failures:
prepend,appendendpointcopyrtolcopyinclude_initialmissinginclude_initialmissingdtypemissinggcorrectionparameterdtypecorrectionparameterdescending,stablemissingdescending,stablemissingmodemissingfull_matricesparameter (mlx hascompute_uvinstead — different semantics)ev-br commentedon Aug 13, 2026
I edited the top post with some details.
prady0t commentedon Aug 14, 2026
@ev-br
Small question. How is it decided what goes in the compat layer and what in the upstream library? For example the
__array_namespace_info__, some libraries have it some have it in compat layer. A few parameters likedevicewould be a bit more complicated, so it makes sense (at least temporarily) to have them in compat (like CuPy).ev-br commentedon Aug 14, 2026
Ideally, the compat layer is ephemeral and goes away at some point. And MLX seems receptive to PRs, so---again ideally---the endgame for MLX is similar to JAX today: there is no compatibility layer, everything lives in MLX itself, and those things where it deviates from the standard (JAX:
__setitem__, data-dependent shapes, MLX: devices, data-dependent shapes) are clearly marked / skipped upstream/prady0t commentedon Aug 14, 2026
Makes sense.
ev-br commentedon Aug 19, 2026
Once ml-explore/mlx#4334 lands, the test suite will run without local patching. Once that's possible, one next step is to send a PR to MLX with a CI setup and an xfail file. Basically, revive ml-explore/mlx#3526 and add
--disable-data-dependent-shapesand add an xfail file (cf https://github.com/data-apis/array-api-strict/blob/main/.github/workflows/array-api-tests.yml#L62).The xfails file will have ~250 entries, of which ~100 are "low-prio" special cases. The remaining ones are also repeated: a missing function causes at least two failures; the missing
__index__causes a half dozen etc.With that, we could ask MLX maintainers if they prefer issues for individual failures, or PRs, or something else entirely.
prady0t commentedon Aug 19, 2026
Since
array-api-testsnow supports multiple xfail files, it would make sense to have them for different builds. Some build-dependent failures were discovered here; there might be a few more.I'm not sure if we have found any platform-dependent failures yet.