can1357/oh-my-pi · warning · Error

spelling range length is too large

Error message

spelling range length is too large

What it means

Same conversion boundary as the 'start is too large' variant, but for the range length: the u32 length is converted to usize for NSRange and the conversion failed. Like the start variant, this is only reachable where usize is narrower than u32 (32-bit targets); it protects the AppKit call from receiving a mangled NSRange.

Source

Thrown at crates/pi-natives/src/spelling.rs:87

	{
		let (reply, result) = flume::bounded(1);
		SPELLING_THREAD
			.send(Box::new(move || {
				let _ = reply.send(work());
			}))
			.map_err(|_| Error::new(Status::GenericFailure, "native spelling thread stopped"))?;
		result
			.recv_async()
			.await
			.map_err(|_| Error::new(Status::GenericFailure, "native spelling thread stopped"))?
	}

	fn ns_range(start: u32, length: u32) -> Result<NSRange> {
		Ok(NSRange {
			location: usize::try_from(start)
				.map_err(|_| Error::new(Status::InvalidArg, "spelling range start is too large"))?,
			length:   usize::try_from(length)
				.map_err(|_| Error::new(Status::InvalidArg, "spelling range length is too large"))?,
		})
	}

	pub fn check(text: &str) -> Result<Vec<SpellingRange>> {
		let checker = checker()?;
		let text = NSString::from_str(text);
		let full = NSRange { location: 0, length: text.length() };
		// `checkString:...` honors `automaticallyIdentifiesLanguages`, selecting
		// the dictionary per detected run; the legacy `checkSpellingOfString:`
		// used only the shared checker's single current language (issue #9334).
		// SAFETY: `options`/`orthography` are nil and `word_count` is null, all
		// documented as valid; the returned array is retained by objc2.
		let results = unsafe {
			checker.checkString_range_types_options_inSpellDocumentWithTag_orthography_wordCount(
				&text,
				full,
				NSTextCheckingType::Spelling.bits(),
				None,

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the range length is a sane, non-negative value bounded by the text length
  2. Clamp length to text.length - start before calling
  3. Use a 64-bit build of the native module

Example fix

// before
native.checkSpelling(text, start, hugeLength);
// after
const safeLen = Math.min(hugeLength >>> 0, text.length - start);
native.checkSpelling(text, start, safeLen);
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isSafeInteger(length) || length < 0 || start + length > text.length) throw new RangeError('length out of range');

Type guard

const isValidLength = (l) => Number.isInteger(l) && l >= 0 && l <= 0xFFFFFFFF;

Try / catch

try {
  return await native.checkSpelling(text, start, length);
} catch (err) {
  if (String(err?.message).includes('spelling range length is too large')) {
    throw new RangeError(`spelling length ${length} rejected`);
  } throw err;
}

Prevention

When it happens

Trigger: Calling a spelling API with a range length that cannot convert to usize — essentially only on 32-bit builds with length values at the top of the u32 range, or a bug producing an out-of-contract length internally.

Common situations: Extremely rare; would surface in 32-bit Electron/Node builds or with corrupted range metadata computed by the caller.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ff71bcfd9032eef3. Report an issue: GitHub.