GoogleChrome/lighthouse · warning · Error
"$" should only be used at the end of the pattern
Error message
"$" should only be used at the end of the pattern
What it means
Thrown by verifyDirective() when a '$' end-of-pattern anchor character appears anywhere except the last position of an Allow or Disallow value. In robots.txt, '$' is a supported extension meaning 'end of URL path' — it is only meaningful and valid at the end. A '$' in the middle is a syntax error that crawlers would misinterpret.
Source
Thrown at core/audits/seo/robots-txt.js:100
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('#');
if (hashIndex !== -1) {
line = line.substr(0, hashIndex);
}
line = line.trim();
View on GitHub (pinned to 9515cd4e58)
Solutions
- Move '$' to the end of the pattern, e.g. 'Disallow: /foo$' to match paths ending in /foo
- If the literal '$' is needed in a path, use '*' wildcard matching instead since '$' cannot appear mid-pattern
- Remove the '$' entirely if no end-anchoring is needed
Example fix
// before Disallow: /download$file // after Disallow: /download*
Defensive patterns
Strategy: validation
Validate before calling
// Validate that '$' only appears at the end of patterns
function validateDollarAnchor(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) {
const value = match[2];
const dollarIdx = value.indexOf('$');
if (dollarIdx !== -1 && dollarIdx !== value.length - 1) {
errors.push(`Line ${idx + 1}: '$' must be at the end of the pattern`);
}
}
});
return errors;
} Try / catch
try {
parseLine(line);
} catch (e) {
// e.message === '"$" should only be used at the end of the pattern'
robotsErrors.push({ line, message: e.message });
} Prevention
- Only use '$' as the last character in Allow/Disallow patterns
- Remember '$' means end-of-URL-path in robots.txt, not a variable
- Run a robots.txt validator before deploying changes
When it happens
Trigger: A robots.txt line like 'Disallow: /foo$bar' where '$' appears mid-pattern. The check verifies `dollarIndex !== -1 && dollarIndex !== directiveValue.length - 1`, so any '$' that is not the final character triggers the throw.
Common situations: Developer treats '$' as a regex variable or literal character rather than a robots.txt end-anchor. Copying regex patterns verbatim into robots.txt. A URL containing literal '$' characters that the developer tried to match without escaping.
Related errors
- No user-agent specified
- Pattern should either be empty, start with "/" or "*"
- Syntax not understood
- Unknown directive
- Invalid sitemap URL
AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13).
Data as JSON: /api/errors/4b60fd4278b098df.
Report an issue: GitHub.