חיפוש הודעות שגיאה של JSON: מטקסט השגיאה ישר לתיקון
שורה תחתונה: אתרו את הסיבה לפי הודעת JSON.parse המדויקת: 12 שגיאות נפוצות ב-Chrome, Firefox ו-Safari, כולל עמודי שגיאה מסוג HTML, קיטוע ופענוח כפול.

שורה תחתונה: כשמופיעה שגיאת JSON.parse, תפסו קודם את המיקום ואת ה-token; מיקום 0 משמעו לבדוק תגובת HTML, BOM או טיפוס שגוי, והודעה מסוג "Expected" משמעה להסתכל על התו הקודם — אל תקראו שורה אחר שורה מהמיקום המדווח.
טקסט השגיאה אינו רעש — הוא התשובה. המפענח אומר לכם איזה תו הוא פגש, למה הוא ציפה ומה הוא קיבל בפועל. חיפוש לפי הודעת השגיאה עדיף על שכתוב המסמך כולו ביד.
לכל שגיאה של JSON.parse() יש שלושה חלקים: המיקום (היסט תו, או שורה/עמודה), הציפייה (Expected...) והמציאות (Unexpected token X, או xxx is not valid JSON). מנועים מנסחים אותם אחרת — Chrome ו-Node (V8) אומרים Expected ',' or '}' after property value in JSON at position 25, Firefox אומר JSON.parse: expected ',' or '}' after property value in object at line 3 column 1, Safari אומר JSON Parse error: Expected ',' or '}' — אבל שלושתם מצביעים על אותה שבירת תחביר. כשאתם מחפשים שגיאה, התעלמו מהניסוח ותפסו את שלוש העובדות: איזה תו, למה ציפה, מה הגיע.
1. טבלת החיפוש של 12 השגיאות
העמודה השמאלית היא הקטע המזוהה ביותר מהקונסולה שלכם (ניסוח V8). וריאנטים של Firefox/Safari מופיעים בסוגריים.
| טקסט השגיאה (V8) | הסיבה האמיתית | התיקון |
|---|---|---|
Unexpected token < in JSON at position 0 |
ה-API החזיר HTML (עמוד 404, תבנית 500, הפניית התחברות, נפילת proxy), לא JSON | בדקו קודם את response.status ואת Content-Type; אל תתקנו את ה-JSON |
Unexpected end of JSON input |
הקלט ריק או מקוטע: גוף ריק, 204, הורדה שנקטעה, העתקה שחסרה את השורה האחרונה | טפלו במקרה הריק, השוו Content-Length כדי למצוא את החיתוך |
Unexpected token o / "[object Object]" is not valid JSON |
אובייקט שכבר פוענח הועבר שוב ל-JSON.parse() והומר למחרוזת |
בדקו typeof; אם זה אובייקט, השתמשו בו ישירות |
"undefined" is not valid JSON |
המשתנה מעולם לא הוקצה (JSON.parse(undefined)) |
אתחלו ערכי ברירת מחדל; הגנו לפני הפענוח |
Expected double-quoted property name in JSON |
פסיק עוקב ({"a": 1,}); המפענח מצפה למפתח נוסף ומוצא } |
הסירו את הפסיק שאחרי הפריט האחרון |
Expected property name or '}' in JSON |
מפתח ללא גרשיים או עם גרשיים בודדים ({name: "Ada"}, {'name': 'Ada'}) |
עטפו כל מפתח בגרשיים כפולים |
Expected ',' or '}' after property value in JSON |
פסיק חסר ({"a": 1 "b": 2}) או הערה אחרי ערך |
הוסיפו את הפסיק; הסירו את ההערה |
Unexpected token '/' |
הערת // או /* */ בתוך JSON |
הסירו אותה, או פענחו את התצורה כ-JSONC |
Bad control character in string literal |
שורה חדשה גולמית, טאב או תו בקרה אחר בטווח U+0000–U+001F בתוך מחרוזת | כתבו \n; ייצרו עם JSON.stringify |
Unterminated string in JSON |
מחרוזת שנפתחה ב-" ומעולם לא נסגרה, או גרש פנימי שלא עבר escape |
בצעו escape לגרשיים פנימיים בתור \" |
Unexpected non-whitespace character after JSON |
שני מסמכים בטקסט אחד: {}{}, NDJSON, עטיפת JSONP |
פצלו לפי שורות ופענחו כל אחת, או השתמשו במפענח NDJSON |
JSON.parse is not a function |
משתנה משלכם מסתיר את JSON הגלובלי |
שנו את שם המשתנה; לעולם אל תקראו לו JSON |
שתי השגיאות הראשונות ראויות למבט מקרוב, כי אף אחת מהן אינה אומרת "ה-JSON שלכם שגוי" — הן אומרות "מה שקיבלתם אינו מה שאתם חושבים שהוא".
2. שלושה מקורות נפוצים לשגיאה במיקום 0
מיקום 0 משמעו שהתו הראשון עצמו בלתי-חוקי. אם שום דבר לא נראה חשוד, התו כנראה בלתי נראה. שלושה חשודים שגרתיים:
ראשון: <, כלומר HTML. זו שגיאת הפענוח הנפוצה ביותר בפרודקשן. כתובת URL שגויה, הפעלה שפג תוקפה והופנתה על ידי ה-gateway, או תבנית שגיאת שרת — הגוף מתחיל ב-<!DOCTYPE html> והמפענח נוטש בתו הראשון. המהלך הנכון הוא לפתוח את פאנל Network ולקרוא את התגובה הגולמית, ואז לתקן את קריאת ה-API, לא את ה-JSON.
שני: BOM או תווי אפס-רוחב. קבצים שנשמרו על ידי Windows Notepad מתחילים לעיתים קרובות ב-BOM של UTF-8 (\uFEFF), וטקסט שהועתק מדפי אינטרנט או מאפליקציות צ'אט עשוי לשאת רווחים באפס רוחב (\u200B–\u200D). בלתי נראה לכם, מובן מאליו למפענח:
// הסירו BOM ותווי אפס-רוחב לפני הפענוח
const cleaned = raw.replace(/^\uFEFF/, '').replace(/[\u200B-\u200D]/g, '');
const data = JSON.parse(cleaned);
שלישי: הטיפוס השגוי. JSON.parse(undefined) מדווח "undefined" is not valid JSON; JSON.parse(someObject) מדווח Unexpected token o (האובייקט הומר ל-"[object Object]", ו-o בלתי-חוקי במיקום 1). שתיהן אומרות "הנתונים כבר מפוענחים" או "מעולם לא היו נתונים". בדקו את הטיפוס, לא את התחביר:
let data = text;
if (typeof data === 'string') {
data = JSON.parse(data); // פענחו רק כשזה באמת מחרוזת
}
3. המיקום מצביע במורד הזרם; הסיבה נמצאת במעלה הזרם
שתי שגיאות מטעות אתכם לגבי המיקום, והן שתי הרשומות המוטעות ביותר בטבלה:
- פסיק חסר:
{"a": 1 "b": 2}מדווחExpected ',' or '}' after property valueעל שורת"b". הדיווח נכון, אבל התיקון שייך לסוף השורה הקודמת. - סוגר סוגר חסר: קינון עמוק שחסר בו
}או]אחד גורם למפענח לבלוע הכול עד סוף הקלט ולדווחUnexpected end of JSON input. המיקום הוא סוף הקובץ; הפער האמיתי יכול להיות הרבה קודם. חפשו אחורה את ה-{או ה-[הפתוח האחרון — ספירת זוגות עדיפה על מבט בעין.
הטכניקה הכללית היא חציה: חתכו את הטקסט לפני המיקום המדווח ופענחו אותו לבד. אם הוא נפענח, הבעיה נמצאת בקרבת המיקום המדווח; אם לא, חצו עוד אחורה. הגבול של הקטע הכושל הראשון הוא מיקום השגיאה האמיתי. בקבצים גדולים, עצבו את המסמך קודם — כשההזחה מיושרת, הרמה החסרה נראית במבט אחד (המעצב ה-JSON המקוון מתאים לזה).
4. ארבעה מצבים "בריאים לכאורה" שנפענחים תקין אבל מתנהגים רע
גרוע משגיאה הוא היעדר שגיאה עם נתונים שגויים. בכל ארבעת המקרים ה-JSON תקין והמפענח מרוצה — הבעיה היא צורת הנתונים:
- קידוד כפול: המסמך כולו עבר
JSON.stringifyפעמיים, כך שהפענוח מניב מחרוזת, לא אובייקט. אםtypeof result === 'string', פענחו שוב — אבל מצאו ותקנו את הסריאליזציה הכפולה במקור. - מפתחות כפולים דורסים בשקט:
{"name": "Tom", "name": "Jerry"}הוא JSON תקין, רוב המפענחים לא מתלוננים, והערך השני מנצח. זה נושך כשממזגים נתונים מכמה מקורות; חשפו אותו עם מאמת JSON קפדני לפני שהוא ינשך אתכם. - NDJSON מטופל כמסמך אחד: APIs זורמים פולטים אובייקט אחד בכל שורה; פענוח הטקסט כולו נכשל עם
Unexpected non-whitespace character after JSON. פצלו לפי\nופענחו שורה אחר שורה. - אובדן דיוק מספרים בשקט: שלמים מעל
2^53 - 1(מזהי snowflake) חוזרים עם הספרות האחרונות מאופסות, בלי שום שגיאה. העבירו ID כמחרוזות.
החוט המקשר: המפענח מאמין שהכול בסדר. לכן כשנתוני API נראים שגויים, הדפיסו קודם את 80 התווים הראשונים של הטקסט הגולמי ואת ה-typeof שלו — אשרו את הצורה לפני שדנים בתוכן.
5. הפכו שגיאות לבלתי אפשריות בזמן הכתיבה
טבלת החיפוש היא הכלי שבדיעבד; מניעה היא הכלי מראש. ארבעה הרגלים מיירטים את רוב השגיאות לפני שהן קורות:
// 1. שתי בדיקות לפני פענוח של כל תגובה
const response = await fetch('/api/users');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ה-API לא החזיר נתונים`);
}
const contentType = response.headers.get('content-type') ?? '';
if (!contentType.includes('application/json')) {
throw new Error(`Expected JSON, got ${contentType}`);
}
const data = await response.json(); // 2. json() כבר מפענח — אל תפענחו שוב
- צרו בסריאליזציה, לעולם אל תחברו:
JSON.stringify()מטפל נכון בגרשיים, בשורות חדשות ובתווי בקרה; מחרוזות שנבנו ביד הן המקור העיקרי ל-Bad control characterול-Unterminated string. - תמיד תפסו: שגיאת
JSON.parseשנזרקת היא קריסה סינכרונית אלא אם משהו תופס אותה. לקלט לא מהימן — localStorage, קבצים חיצוניים — בלוק ה-catch צריך ערך ברירת מחדל או דיווח שגיאה מפורש. - האצילו מבנה ל-Schema: תחביר תקין אינו אומר מבנה תקין. שדות חסרים וטיפוסים שגויים שייכים לאימות JSON Schema בגבול; ראו מה JSON Schema פותר.
6. מסלול ההחלטה המהיר
דחסו את המאמר כולו לסדר החלטה אחד. כשרואים שגיאה, תפסו קודם את המיקום ואת ה-token:
- מיקום 0 → בדקו את שלושת המקורות:
<(HTML), BOM, טיפוס שגוי; end of input→ בדקו גוף ריק או מקוטע, ואז חפשו אחורה סוגריים לא סגורים;Expected ...→ הסתכלו על התו הקודם; זה בדרך כלל פסיק או גרש חסר;after JSON data→ כמה מסמכים חוברו יחד; פצלו לפי שורה;- נפענח תקין אבל הנתונים נראים שגויים → הריצו את ארבע בדיקות ה"בריא לכאורה".
בשילוב עם התיוג הצעד-אחר-צעד באיך לתקן שגיאות פענוח JSON, 90% מבעיות הפענוח נפתרות בתוך חמש דקות. שמרו את טקסט השגיאה עצמו במועדפים — זה יומן הדיבוג שהמפענח כתב עבורכם, הניסוח שלו משתנה פעם בשלוש שנים, וחיפוש אחד משתלם לשנה.
מה המשמעות של "Unexpected token in JSON"?
המפענח פגע בתו שהוא בלתי-חוקי באותו מקום בדקדוק JSON. ה-token הוא התו הנדחה: < משמעו בדרך כלל שה-API החזיר HTML, ' משמעו גרשיים בודדים, / משמעו הערה, ואות רגילה משמעה בדרך כלל מפתח ללא גרשיים או literal הקיים רק ב-JavaScript כמו undefined או NaN. קראו קודם את ה-token, אחר כך את המיקום, והסיבה מצטמצמת לאחת.
איך מתקנים "Unexpected end of JSON input"?
שני מקורות: קלט ריק (גוף תגובה ריק, או מחרוזת ריקה ב-localStorage) או קלט מקוטע (הורדה שנקטעה, העתקה שחסרה את השורה האחרונה, מגבלת גודל). טפלו במקרה הריק עם if (!text) return; ואז אמתו שלמות וסגרו את ה-{, ה-[ או ה-" הפתוח האחרון. שימו לב שהשגיאה יכולה לנבוע גם מסוגר חסר בקינון עמוק — המיקום פשוט במקרה הוא סוף הקובץ.
למה Chrome, Firefox ו-Safari מדווחים על שגיאות אחרת?
שלושת הדפדפנים מגיעים עם מנועי JS שונים (V8, SpiderMonkey, JavaScriptCore), וכל אחד מנסח את השגיאות שלו בדרכו; MDN מתעד את כל הווריאנטים הרשמיים. אבל לכל שלוש השגיאות יש את אותם שלושה מרכיבים — מיקום, ציפייה, מציאות — עם סמנטיקה של התאמה אחד-לאחד. תרגמו לניסוח V8 והשתמשו בטבלה הזו כמו שהיא.
מיקום השגיאה מצביע על מקום שנראה תקין — מה עכשיו?
השגיאה האמיתית נמצאת קודם. מקרים אופייניים: פסיק חסר (מדווח בשורה הבאה) וסוגר סוגר חסר (מדווח בסוף הקובץ). צעדו אחורה מהמיקום המדווח token אחר token, או חצו: פענחו את המחצית הראשונה לבד, והגבול של הקטע הכושל הראשון הוא מיקום השגיאה האמיתי.