microsoft/TypeScript · error · Error

Exactly one refactor range is allowed per test.

Error message

Exactly one refactor range is allowed per test.

What it means

Thrown by verifyApplicableRefactorAvailableForRange when the test data does not contain exactly one defined range (via [range ... ] markers). Range-based refactor verification requires a single range to evaluate applicable refactors against; zero or multiple ranges make the check ambiguous, so the harness refuses to proceed.

Source

Thrown at src/harness/fourslashImpl.ts:4084

                this.raiseError(`${refactors.length} available refactors both have name ${name} and action ${actionName}`);
            }
        }
    }

    public verifyRefactorKindsAvailable(kind: string, expected: string[], preferences: {} = ts.emptyOptions): void {
        const refactors = this.getApplicableRefactorsAtSelection("invoked", kind, preferences);
        const availableKinds = ts.flatMap(refactors, refactor => refactor.actions).map(action => action.kind);
        assert.deepEqual(availableKinds.slice().sort(), expected.slice().sort(), `Expected kinds to be equal`);
    }

    public verifyRefactorsAvailable(names: readonly string[]): void {
        assert.deepEqual(unique(this.getApplicableRefactorsAtSelection(), r => r.name), names);
    }

    public verifyApplicableRefactorAvailableForRange(negative: boolean): void {
        const ranges = this.getRanges();
        if (!(ranges && ranges.length === 1)) {
            throw new Error("Exactly one refactor range is allowed per test.");
        }

        const isAvailable = this.getApplicableRefactors(ts.first(ranges)).length > 0;
        if (negative && isAvailable) {
            this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected no refactor but found some.`);
        }
        if (!negative && !isAvailable) {
            this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected a refactor but found none.`);
        }
    }

    public applyRefactor({ refactorName, actionName, actionDescription, newContent: newContentWithRenameMarker, triggerReason }: FourSlashInterface.ApplyRefactorOptions): void {
        const range = this.getSelection();
        const refactors = this.getApplicableRefactorsAtSelection(triggerReason);
        const refactorsWithName = refactors.filter(r => r.name === refactorName);
        if (refactorsWithName.length === 0) {
            this.raiseError(`The expected refactor: ${refactorName} is not available at the marker location.\nAvailable refactors: ${refactors.map(r => r.name)}`);
        }

View on GitHub (pinned to b465fdbfe1)

Solutions

  1. Add exactly one range to the fourslash file using [| ... |] (or the equivalent range marker syntax) around the code region to check.
  2. Remove any extra range markers so getRanges().length === 1.
  3. If you need multiple ranges, restructure into separate test functions or use a different verification method per range.

Example fix

// before — no range markers
verify.applicableRefactorAvailableForRange();
// after
// in test file: [|export function foo() {}|]
verify.applicableRefactorAvailableForRange();
Defensive patterns

Strategy: validation

Validate before calling

const ranges = state.getRanges();
if (ranges && ranges.length === 1) {
    verify.applicableRefactorAvailableForRange();
} else {
    throw new Error(`Test needs exactly one range, found ${ranges ? ranges.length : 0}`);
}

Prevention

When it happens

Trigger: Calling verify.applicableRefactorAvailableForRange or verify.noApplicableRefactorAvailableForRange in a fourslash test whose .ts source has zero [range markers] or more than one [range ... ...] region. getRanges() returns undefined or a multi-element array.

Common situations: Test author copies a server-based refactor test and forgets to bracket the target code with [| ... |] range markers, or leaves an extra range from a previous test variant. The negative/positive overload both require the single range.

Related errors


AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12). Data as JSON: /api/errors/944ec612532830bd. Report an issue: GitHub.