GoogleChrome/lighthouse · warning · Error

Pattern should either be empty, start with "/" or "*"

Error message

Pattern should either be empty, start with "/" or "*"

What it means

Thrown by verifyDirective() when an Allow or Disallow directive has a pattern value that is non-empty and does not start with '/' or '*'. The robots exclusion standard requires path patterns to be rooted at '/' (absolute path) or use '*' as a wildcard anchor. This enforces syntactic correctness so crawlers can reliably interpret crawl rules.

Source

Thrown at core/audits/seo/robots-txt.js:94

    try {
      sitemapUrl = new URL(directiveValue);
    } catch (e) {
      throw new Error('Invalid sitemap URL');
    }

    if (!SITEMAP_VALID_PROTOCOLS.has(sitemapUrl.protocol)) {
      throw new Error('Invalid sitemap URL protocol');
    }
  }

  if (directiveName === DIRECTIVE_USER_AGENT && !directiveValue) {
    throw new Error('No user-agent specified');
  }

  if (directiveName === DIRECTIVE_ALLOW || directiveName === DIRECTIVE_DISALLOW) {
    if (directiveValue !== '' && directiveValue[0] !== '/' && directiveValue[0] !== '*') {
      throw new Error('Pattern should either be empty, start with "/" or "*"');
    }

    const dollarIndex = directiveValue.indexOf('$');

    if (dollarIndex !== -1 && dollarIndex !== directiveValue.length - 1) {
      throw new Error('"$" should only be used at the end of the pattern');
    }
  }
}

/**
 * @param {string} line single line from a robots.txt file
 * @throws will throw an exception if given line has errors
 * @return {{directive: string, value: string}|null}
 */
function parseLine(line) {
  const hashIndex = line.indexOf('#');

View on GitHub (pinned to 9515cd4e58)

Solutions

  1. Prefix the pattern with '/', e.g. 'Disallow: /private'
  2. If a wildcard is intended, prefix with '*', e.g. 'Disallow: /*?id='
  3. If you want to allow/disallow everything, use '/' or '*' accordingly

Example fix

// before
Disallow: private

// after
Disallow: /private
Defensive patterns

Strategy: validation

Validate before calling

// Validate Allow/Disallow patterns before parsing
function validatePatterns(content) {
  const lines = content.split(/\r\n|\r|\n/);
  const errors = [];
  lines.forEach((line, idx) => {
    const trimmed = line.split('#')[0].trim();
    const match = /^(allow|disallow)\s*:\s*(.*)$/i.exec(trimmed);
    if (match && match[2] !== '' && match[2][0] !== '/' && match[2][0] !== '*') {
      errors.push(`Line ${idx + 1}: Pattern must start with '/' or '*'`);
    }
  });
  return errors;
}

Try / catch

try {
  parseLine(line);
} catch (e) {
  // e.message === 'Pattern should either be empty, start with "/" or "*"'
  robotsErrors.push({ line, message: e.message });
}

Prevention

When it happens

Trigger: A robots.txt line like 'Disallow: private' (no leading slash), 'Disallow: ?id=5' (starts with '?'), or 'Allow: .jpg$' (starts with '.'). Any Allow/Disallow value whose first character is not '/', '*', or empty triggers it.

Common situations: Developer writes a relative-style path instead of an absolute server path. Copying URL patterns from .htaccess or nginx configs that use different anchoring conventions. Forgetting that robots.txt patterns are path-based, not regex-based.

Related errors


AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13). Data as JSON: /api/errors/b16e553e57f01996. Report an issue: GitHub.