```ts
/**
 * Parses an option string into [key, value] pairs.
 * @param segment - The option segment to parse.
 * @returns A tuple containing the key and value.
 */
export function parseOption(segment: string): string[] {
    const equalsIndex = segment.indexOf('=');
    if (equalsIndex === -1 || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(segment.substring(0, equalsIndex))) {
        throw new Error('Invalid option format');
    }
    let value = segment.substring(equalsIndex + 1).trim();
    if (value.startsWith('"') && value.endsWith('"')) {
        value = value.slice(1, -1);
    } else if (value.startsWith('"')) {
        throw new Error('Unquoted string missing closing quote');
    }
    return [segment.substring(0, equalsIndex), value];
}

/**
 * Splits an options string into [key, value] pairs.
 * @param input - The options string to split.
 * @returns An array of [key, value] tuples.
 */
export function scanPairs(input: string): string[][] {
    if (typeof input !== 'string' || input === '') {
        throw new Error('Invalid input');
    }
    const result: string[][] = [];
    let currentSegment = '';
    let inQuotes = false;

    for (const char of input) {
        if (char === '"' && !inQuotes) {
            inQuotes = true;
        } else if (char === '"' && inQuotes) {
            inQuotes = false;
        } else if (char === ';' && !inQuotes) {
            result.push(parseOption(currentSegment.trim()));
            currentSegment = '';
        } else {
            currentSegment += char;
        }
    }

    if (currentSegment) {
        result.push(parseOption(currentSegment.trim()));
    }

    const keys = new Set<string>();
    for (const [key, value] of result) {
        if (keys.has(key)) {
            throw new Error('Duplicate key');
        }
        keys.add(key);
    }

    return result;
}
```