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
- Prefix the pattern with '/', e.g. 'Disallow: /private'
- If a wildcard is intended, prefix with '*', e.g. 'Disallow: /*?id='
- 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
- Always prefix Allow/Disallow paths with '/' for absolute paths
- Use '*' only for wildcard matching at the start of patterns
- Test robots.txt rules with Google's robots.txt Tester in Search Console
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
- No user-agent specified
- "$" should only be used at the end of the pattern
- Syntax not understood
- Unknown directive
- Invalid sitemap URL
AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13).
Data as JSON: /api/errors/b16e553e57f01996.
Report an issue: GitHub.