Dev.to WebDev 🛠 Dev 👁 0 📖 4 min read

Chrome Web Store Rejection Codes: Fix the Top 4 in a Day

Originally published on ExtensionLaunch. A Chrome Web Store rejection usually arrives as a policy name and a code like "Blue Argon" or "Purple Potassium", with little detail about what the reviewer saw. Every code maps

Originally published on ExtensionLaunch.

A Chrome Web Store rejection usually arrives as a policy name and a code like "Blue Argon" or "Purple Potassium", with little detail about what the reviewer saw. Every code maps to a specific policy, and the four that hit first-time publishers most often are usually a one-day fix. Here's how to read the code, fix the cause, and choose between resubmitting and appealing.

First, check which kind of action you got

Not every email from the store carries the same risk:

  • Rejection: the new submission or update failed review. Your live version (if any) is untouched and users are not told. Fix it and resubmit.
  • Warning: applies to an item that is already published. It stays live, but you typically get 7 to 30 days to fix it before it comes down.
  • Takedown: the item is pulled from the store, and after several weeks Chrome disables it for existing users.

A warning is a deadline, so treat it as urgent.

The color is the category

The color tells you the policy family before you open the docs:

Color What it covers Common IDs
Blue Manifest V3 rules, prohibited products Blue Argon (remote code)
Purple Permissions and user data Purple Potassium, Purple Lithium, Purple Nickel
Yellow Broken features, thin functionality, metadata Yellow Magnesium, Yellow Zinc, Yellow Argon, Yellow Potassium
Red Deception and single purpose Red Magnesium, Red Titanium, Red Zinc
Grey Content Adult, gambling, violence and similar

The four codes most first submissions hit

Purple Potassium: excessive permissions

This is the most common one. Your manifest asks for permissions you don't use, or broader access than you need. Usual suspects:

  • tabs only unlocks url, pendingUrl, title and favIconUrl on Tab objects. Most chrome.tabs methods work without it.
  • activeTab isn't required just to call tabs.query() or tabs.sendMessage().
  • cookies is for chrome.cookies, not document.cookie.
  • storage is for chrome.storage, not localStorage or IndexedDB.

Delete anything you can't point to in code, and move broad host access to runtime:

{
  "permissions": ["activeTab"],
  "optional_host_permissions": ["https://*.yourapp.com/*"]
}

Then make sure the justifications on the Privacy practices tab match what's left.

Blue Argon: remote code

Manifest V3 requires all executable code inside the package. A CDN <script> tag, eval() on a server string, or an interpreter running remote commands all trigger it. Fetching data is fine; fetching logic is not. Scan the folder you zip:

grep -rnE "<script[^>]*src=[\"']https?://|\beval\(|new Function\(" dist/

Also answer the remote-code question on the Privacy practices tab honestly, or you'll pick up a disclosure problem on top of this one.

Yellow Magnesium: functionality not working

The reviewer couldn't make it work. Usually it's packaging, not logic: a file in manifest.json missing from the ZIP, a case mismatch (Popup.html vs popup.html), a backend that was down, or a login the reviewer didn't have. A quick pre-upload check:

// verify-manifest.mjs  usage: node verify-manifest.mjs dist
import { readFileSync, readdirSync } from 'node:fs';
import { join, dirname, basename } from 'node:path';

const dir = process.argv[2] || '.';
const m = JSON.parse(readFileSync(join(dir, 'manifest.json'), 'utf8'));
const list = (v) => (typeof v === 'string' ? [v] : Object.values(v || {}));

const refs = [
  m.background?.service_worker,
  m.action?.default_popup,
  m.options_ui?.page ?? m.options_page,
  m.side_panel?.default_path,
  ...list(m.icons),
  ...list(m.action?.default_icon),
  ...(m.content_scripts || []).flatMap((cs) => [...(cs.js || []), ...(cs.css || [])]),
].filter(Boolean);

// Compare exact file names so a case mismatch fails even on macOS
const exists = (p) => {
  try { return readdirSync(dirname(p)).includes(basename(p)); } catch { return false; }
};
const missing = refs.filter((r) => !exists(join(dir, r)));

if (missing.length) {
  console.error('Missing from package:', missing);
  process.exit(1);
}
console.log(`OK: all ${refs.length} referenced files are present.`);

If anything needs an account, fill in the Test instructions section in the Developer Dashboard with credentials and steps.

Purple Lithium: privacy policy

Your privacy policy is missing, not in the Privacy tab's policy field, unreachable, or silent on how data is collected, used and shared. Put a working URL in that field, not just your description. Its sibling Purple Nickel means collecting data without in-product disclosure and consent: show what you collect and wait for a yes.

Codes you can't fix with an update

For Red Titanium (obfuscation) and Red Zinc (deceptive installation), Google says to publish a new extension rather than patch the old one. Minification is fine; Base64 or character-encoding tricks count as obfuscation, so disable string encoding in your build before submitting.

Resubmit or appeal?

  • Resubmit when the reviewer was right. Bump the version, update the Privacy tab, and note non-obvious fixes in test instructions. To swap a package already queued, use Cancel review, upload the fix, and resubmit.
  • Appeal only when you're sure you comply. Name the reference ID, quote the policy, point to the file and line that uses the flagged permission, and give reproduction steps. Replies can take up to three days.

Launch tip: uncheck automatic publishing when you submit. You get up to 30 days after approval to publish manually, so launch day lands on an approved version.

Key takeaways

  • The code's color tells you the policy family.
  • Purple Potassium, Blue Argon, Yellow Magnesium and Purple Lithium are the usual first-submission rejections, all fixable in a day.
  • Test the exact ZIP you upload, not your dev build.
  • Red Titanium and Red Zinc mean a new listing, so keep obfuscation out of your build.
  • Resubmit when the reviewer is right; appeal only with evidence.

The full guide to Chrome Web Store rejection codes and how to fix each one maps every ID in the reference table and includes a pre-submission checklist. Once you're approved, you can launch your browser extension on ExtensionLaunch to get its first upvotes and reviews.

What was the reason for your most frustrating Chrome Web Store rejection, and what fixed it in the end?

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.