gildas-lormeau/SingleFile · warning · Error

Duplicate profile name

Error message

Duplicate profile name

What it means

createProfile validates that the requested profile name is unique across existing profiles before copying the source profile. If a profile with that name already exists, it refuses to overwrite silently and throws.

Source

Thrown at src/core/bg/config.js:545

			Object.keys(syncConfig)
				.filter(keyName => keyName.startsWith(PROFILE_NAME_PREFIX))
				.forEach(keyName => profiles[keyName] = syncConfig[keyName]);
			await browser.storage.local.set(profiles);
		}
		configStorage = browser.storage.local;
		await upgrade();
		return {};
	}
	if (message.method.endsWith(".isSync")) {
		return { sync: (await browser.storage.local.get()).sync };
	}
	return {};
}

async function createProfile(profileName, fromProfileName) {
	const profileNames = await getProfileNames();
	if (profileNames.includes(profileName)) {
		throw new Error("Duplicate profile name");
	}
	const profileFrom = await getProfile(fromProfileName);
	const profile = JSON.parse(JSON.stringify(profileFrom));
	profile.customShortcut = null;
	await setProfile(profileName, profile);
}

async function getProfiles() {
	await pendingUpgradePromise;
	const profileKeyNames = await getProfileKeyNames();
	const profiles = await configStorage.get(profileKeyNames);
	const result = {};
	Object.keys(profiles).forEach(profileName => result[profileName.substring(PROFILE_NAME_PREFIX.length)] = profiles[profileName]);
	return result;
}

async function getOptions(url, autoSave) {
	await pendingUpgradePromise;

View on GitHub (pinned to 517fb7c5cf)

Solutions

  1. Generate a unique name first (check getProfileNames() or append a suffix)
  2. Catch the error and prompt the user for a different name
  3. If overwrite is intended, use updateProfile on the existing profile instead of createProfile
  4. Debounce/idempotent-guard the UI action that triggers creation

Example fix

// before
await config.createProfile('work', 'default');
// after
const names = await config.getProfileNames();
const name = names.includes('work') ? 'work-2' : 'work';
await config.createProfile(name, 'default');
Defensive patterns

Strategy: validation

Validate before calling

const names = await config.getProfileNames();
if (names.includes(newName)) throw new Error('choose another name');

Type guard

const nameIsFree = async (n) => !(await config.getProfileNames()).includes(n);

Try / catch

try { await createProfile(name, from); } catch (e) { if (e.message === 'Duplicate profile name') name = await suggestUniqueName(name); else throw e; }

Prevention

When it happens

Trigger: createProfile(name, fromName) called with a name already present in getProfileNames() — e.g. duplicate UI submissions, replayed messages via onMessage, or programmatic creation without checking names.

Common situations: Double-clicking a create button in the options UI; importing settings that already contain the profile; scripts generating non-unique names from timestamps or counters that collide.

Related errors


AI-assisted analysis of gildas-lormeau/SingleFile@517fb7c5cf (2026-09-01). Data as JSON: /api/errors/ae37e60580934050. Report an issue: GitHub.