# Multi-dimensional indices are incompatible with \`end\` index

**URL:** <https://discourse.julialang.org/t/multi-dimensional-indices-are-incompatible-with-end-index/134886>\
**Category:** Internals & Design\
**Tags:** indexing, arrays, lowering\
**Created:** [January 5, 2026, 12:04pm UTC](https://discourse.julialang.org/t/multi-dimensional-indices-are-incompatible-with-end-index/134886 "2026-01-05T12:04:49Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![aryavorskiy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aryavorskiy/32/43466_2.png) [@aryavorskiy](https://discourse.julialang.org/u/aryavorskiy)\
**Post date:** [January 5, 2026, 12:04pm UTC](https://discourse.julialang.org/t/multi-dimensional-indices-are-incompatible-with-end-index/134886/1 "2026-01-05T12:04:49Z")

</div>

Julia allows to access the last index in the axis of an array using the `end` keyword by lowering it to `lastindex` in a rather predictable way:

```julia
A = rand(5, 5, 2)
A[1:end - 1, end ÷ 2, :] # lowers to A[1:lastindex(A, 1) - 1, lastindex(A, 2) ÷ 2, :]

```

This silently assumes that all indices are one-dimensional, which leads to extremely sneaky errors

```julia
mask = rand(5, 5) .> 0.5
A[mask, end] # BoundsError, because `end` lowers to `lastindex(A, 2)` == 5

```

Now, this is likely a known issue, it is even [raised in the docs](https://docs.julialang.org/en/v1/manual/arrays/#Warning-3d505b4723551dec), though only for `CartesianIndex`. However, since these types of errors are silent (so if A had shape (5, 5, 10) by sheer bad luck, I would have gotten wrong results without any error), so I believe we can’t just leave it this way.

Probably a good idea is update the docs to make more emphasis on this issue: make the warning message brighter and move it to the part where the `end` keyword is introduced. Another idea is changing how code like this is lowered (and probably implement it in JuliaLowering.jl), I can see how it can be done in two ways:

- Make this behavior throw an error. For example, we can wrap `A` into a struct like `Require1DIndexing` and override its `getindex`/`setindex` to check if all indices are one-dimensional.
- Check the dimensionality of each index on the lowering stage: create a local variable `index_dim::Int = 1`, then take the first index and replace `end` with `lastindex(A, index_dim)`, then increase `index_dim` by the dimensionality of the first index, rinse, repeat.

Which is the better way to solve it here?

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [January 5, 2026, 2:14pm UTC](https://discourse.julialang.org/t/multi-dimensional-indices-are-incompatible-with-end-index/134886/2 "2026-01-05T14:14:41Z")

</div>

Yeah, this is a well known issue. Good catch that the warning box should also include boolean masks (and other custom index types like EllipsisNotation.jl), too. Some other ideas on how to solve this are in this issue:

> <https://github.com/JuliaLang/julia/issues/35681>
>
> Indexing by \`end\` is lowered here to \`lastindex(A, 2)\`, which isn't correct when… the other indices take up more than one dimension (or none):
> \`\`\`julia
> julia\> zeros(2,2,1)\[CartesianIndex(2,2), 1\]
> 0.0
> 
> julia\> zeros(2,2,1)\[CartesianIndex(2,2), end\]
> ERROR: BoundsError: attempt to access 2×2×1 Array{Float64,3} at index \[2, 2, 2\]
> Stacktrace:
> \[1\] getindex at ./array.jl:788 \[inlined\]
> \[2\] getindex(::Array{Float64,3}, ::CartesianIndex{2}, ::Int64) at ./multidimensional.jl:552
> \[3\] top-level scope at REPL\[19\]:1
> 
> julia\> g(A, i, j) = A\[i, end, j\];
> 
> julia\> @code\_lowered g(zeros(4,3,2), CartesianIndex(1,1), CartesianIndex())
> CodeInfo(
> 1 ─ %1 = Base.lastindex(A, 2)
> │ %2 = Base.getindex(A, i, %1, j)
> └── return %2
> )
> \`\`\`
> I assumed this worked, but @c42f actually checked!
