The answer is intimated in ?arrows
:
The direction of a zero-length arrow is indeterminate, and hence so is the direction of the arrowheads. To allow for rounding error, arrowheads are omitted (with a warning) on any arrow of length less than 1/1000 inch.
Which of course begs the question -- What is an inch?
That Q&A was centered around a related issue, but the learnings can also be applied here:
png('~/Desktop/arrows.png', height = 240, width = 240)
plot(NA, xlim = c(-1, 1), ylim = c(-3, 3))
# get each arrow's length by converting x and y coords to inches
units = par(c('usr', 'pin'))
x_to_inches = with(units, pin[1L]/diff(usr[1:2]))
y_to_inches = with(units, pin[2L]/diff(usr[3:4]))
dists = sqrt((x_to_inches * diff(x))**2 + (y_to_inches * diff(y))**2)
# which arrows are the culprits?
idx = which(dists < .001)
# option: remove the arrow base & head from the culprit pair(s)
arrows(x[-c(N, idx)], y[-c(N, idx)],
x[-c(1L, idx + 1L)], y[-c(1L, idx + 1L)])
dev.off()
You can see here in the R source that this approach is almost identical to that used (at the C level) to generate this warning in the first place.
Something that's always bugged me but never enough to sit down and hash it out.