laurent22/joplin · error · Error

${errorPrefix}: Value for key ${key} is ${typeof value}, not

Error message

${errorPrefix}: Value for key ${key} is ${typeof value}, not string.

What it means

Thrown while iterating `Object.entries(json.prompts)` in `WhisperConfig.processPrompts` when one of the prompt values is not a string. Each prompt must map a locale key to a string.

Source

Thrown at packages/app-mobile/services/voiceTyping/whisper.ts:31

class WhisperConfig {
	public prompts: Map<string, string> = new Map();
	public supportsShortAudioCtx = false;
	public stringReplacements: [string, string][] = [];
	public regexReplacements: [RegExp, string][] = [];

	public constructor(json: unknown) {
		const errorPrefix = 'Whisper config';
		if (typeof json !== 'object') throw new Error('Whisper config is not an object');

		const processPrompts = () => {
			if (!('prompts' in json)) return;
			if (typeof json.prompts !== 'object') {
				throw new Error(`${errorPrefix}: Field "prompts" is not an object`);
			}

			for (const [key, value] of Object.entries(json.prompts)) {
				if (typeof value !== 'string') {
					throw new Error(`${errorPrefix}: Value for key ${key} is ${typeof value}, not string.`);
				}
				this.prompts.set(key, value);
			}
		};
		const processOutputSettings = () => {
			if (!('output' in json)) return;
			if (typeof json.output !== 'object') {
				throw new Error(`${errorPrefix}: Field "output" is not an object`);
			}

			const getReplacements = (key: string, value: unknown) => {
				if (!Array.isArray(value)) {
					throw new Error(`${errorPrefix}: ${key} must be an array`);
				}

				const results: [string, string][] = [];
				for (const replacement of value) {
					if (!Array.isArray(replacement)) {

View on GitHub (pinned to 2654b33620)

Solutions

  1. Ensure every value under `prompts` is a string literal.
  2. Re-download the model bundle for a known-good config.
  3. Add a JSON schema check that `prompts` is `Record<string,string>`.

Example fix

// before
"prompts": { "en": 123 }

// after
"prompts": { "en": "transcribe audio" }
Defensive patterns

Strategy: validation

Validate before calling

for (const [k, v] of Object.entries(config.prompts ?? {})) {
  if (typeof v !== 'string') {
    throw new Error(`Whisper config: prompt value for ${k} must be a string`);
  }
}

Type guard

const isStringRecord = (v: unknown): v is Record<string, string> =>
  !!v && typeof v === 'object' && !Array.isArray(v) &&
  Object.values(v).every(x => typeof x === 'string');

Try / catch

null

Prevention

When it happens

Trigger: A config like `{ "prompts": { "en": 123 } }` or `{ "prompts": { "en": { ... } } }` — any value that fails `typeof value !== 'string'`. The offending key and the actual `typeof` are interpolated.

Common situations: Authoring error where a prompt value is a number or nested object; copy-paste mistake; locale key without a string value.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/06fe931edf61128f. Report an issue: GitHub.