{"record":{"id":"aea831fbbccb76a2","repo":"shadcn-ui/ui","slug":"could-not-update-components-json-please-manually","errorCode":null,"errorMessage":"Could not update components.json. Please manually set `rtl: true`.","messagePattern":"Could not update components\\.json\\. Please manually set `rtl: true`\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/shadcn/src/migrations/migrate-rtl.ts","lineNumber":114,"sourceCode":"      logger.info(\"Migration cancelled.\")\n      process.exit(0)\n    }\n  }\n\n  // Update components.json to set rtl: true.\n  const configSpinner = spinner(\"Updating components.json...\").start()\n  try {\n    const configPath = path.resolve(config.resolvedPaths.cwd, \"components.json\")\n    const existingConfig = JSON.parse(await fs.readFile(configPath, \"utf-8\"))\n    existingConfig.rtl = true\n    await fs.writeFile(\n      configPath,\n      JSON.stringify(existingConfig, null, 2) + \"\\n\"\n    )\n    configSpinner.succeed(\"Updated components.json.\")\n  } catch {\n    configSpinner.fail(\"Failed to update components.json.\")\n    throw new Error(\n      \"Could not update components.json. Please manually set `rtl: true`.\"\n    )\n  }\n\n  // Transform files.\n  const migrationSpinner = spinner(\"Migrating files to RTL...\").start()\n  let transformedCount = 0\n  const filesNeedingReview: string[] = []\n\n  await Promise.all(\n    files.map(async (file) => {\n      migrationSpinner.text = `Migrating ${file}...`\n\n      const filePath = path.join(basePath, file)\n      const content = await fs.readFile(filePath, \"utf-8\")\n      const transformed = await transformDirection(content, true)\n\n      // Only write if content changed.","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/packages/shadcn/src/migrations/migrate-rtl.ts#L96-L132","documentation":"Thrown by migrateRtl after a try/catch around reading, parsing, and writing components.json fails for any reason. The original error is swallowed by the catch (no binding), and this generic message is thrown instructing the user to manually set `rtl: true`. The file write is the last step before file transformation, so on failure no files have been transformed yet.","triggerScenarios":"components.json does not exist at config.resolvedPaths.cwd; the file exists but contains invalid JSON; the file is read-protected or the directory is read-only; a PermissionError or disk error during writeFile.","commonSituations":"Running in a read-only filesystem (CI container with mounted read-only config); components.json was renamed/moved after init; JSON was hand-edited and broke syntax; permissions issue.","solutions":["Manually edit components.json to add `\"rtl\": true` at the top level.","Verify components.json exists at the project root and is valid JSON (`node -e \"JSON.parse(require('fs').readFileSync('components.json'))\"`).","Check write permissions on the file and directory (`ls -l components.json`).","If running in CI, ensure the working directory is writable."],"exampleFix":"// before — components.json missing or invalid\n// (the migrator failed to update it)\n\n// after — manually add the rtl flag\n{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"new-york\",\n  \"rtl\": true,\n  \"aliases\": { ... }\n}","handlingStrategy":"try-catch","validationCode":"import fs from 'fs/promises'\nimport path from 'path'\n\nasync function assertComponentsJsonWritable(cwd: string) {\n  const p = path.resolve(cwd, 'components.json')\n  const txt = await fs.readFile(p, 'utf-8')\n  JSON.parse(txt) // throws on invalid JSON\n  await fs.access(path.dirname(p), fs.constants.W_OK)\n}\n\nawait assertComponentsJsonWritable(config.resolvedPaths.cwd)","typeGuard":null,"tryCatchPattern":"try {\n  await migrateRtl(config, { yes: true })\n} catch (e) {\n  if (e instanceof Error && e.message.includes('manually set `rtl: true`')) {\n    logger.warn('Auto-update of components.json failed. Edit it manually to add \"rtl\": true, then re-run.')\n    // optionally write the flag yourself with a known-good serializer\n  } else throw e\n}","preventionTips":["Validate components.json parses with `JSON.parse` before running.","Ensure the project directory is writable in CI containers.","Keep components.json under source control so corruption is caught in review."],"tags":["migration","rtl","config","components-json","filesystem"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}