תקלות בטפסים — אבחון לפי תסמין
התסמינים בקליטת טפסים מטעים: קוד הסטטוס כמעט אף פעם לא מספר את הסיפור. 200 יכול להיות כישלון שקט, ו‑400 הוא הסטטוס של כמעט כל תקלה — ההבחנה היא בגוף התשובה.
התחילו מהטבלה, ורדו לפירוט של התסמין שלכם.
| התסמין (גוף התשובה) | הסטטוס | הסיבה השכיחה | הבדיקה |
|---|---|---|---|
<שם הדגל> is Disabled |
400 |
דגל ה‑Config כבוי, חסר, או שהודלק הדגל השני | ↓ |
missing "phone" |
400 |
phone לא נשלח, או נשלח עם קידומת |
↓ |
missing "PhoneNumber" or "Email" |
400 |
ValidatePhoneOrEmail דלוק והקלט לא תקין |
↓ |
User function not found |
400 |
שם נקודת קצה שלא קיים — למשל השם הישן web2lead |
↓ |
{"code":103,"message":"Class X does not exist."} |
400 |
ערך table שאינו שם מחלקה קיים |
↓ |
{"code":111,"message":"schema mismatch …"} |
400 |
Pointer באורך ≠ 10 ב‑account_*, בוליאני כמספר, תאריך לא מרופד, שדה File |
↓ |
200 ושדה Pointer ריק |
200 |
ב‑table_*: אורך ≠ 10 או אובייקט Pointer — נזרק בשקט; בשתי הקבוצות: SaleStatusId |
↓ |
200 ושדה רגיל לא נשמר |
200 |
שם השדה לא קיים בסכימה — נזרק בשקט | ↓ |
| איש קשר הוכפל בכל פנייה | 200 |
account_PhoneNumber במקום phone; טלפון שמור בפורמט לא נסרק; אימייל באותיות אחרות |
↓ |
| איש קשר קיים לא התעדכן | 200 |
התנהגות מתוכננת | ↓ |
404 Not Found |
404 |
הכתובת מתחת ל‑/parse/ |
↓ |
code 119 |
400 |
ניסיון כתיבה ישירה ל‑REST במקום דרך נקודת הקצה | ↓ |
| הדפדפן חוסם — CORS | — | כמעט תמיד סימפטום של משהו אחר | ↓ |
הדגל כבוי — … is Disabled
Section titled “הדגל כבוי — … is Disabled”הסיבה בכ‑9 מתוך 10 מקרים: דגל ה‑Config. לא הקוד, לא ההרשאות, לא ה‑Application Id.
הבדיקה מתפצלת לשלוש שאלות, בסדר הזה:
א. איזה דגל? הם נפרדים לגמרי:
| נקודת הקצה | הדגל | ההודעה (בסטטוס 400) |
|---|---|---|
web2table |
AcceptWebToTable |
AcceptWebToTable is Disabled |
web2case |
AcceptWebToCaseLeads |
AcceptWebToCaseLeads is Disabled |
getlead |
AcceptWebLeads |
AcceptWebLeads is Disabled — אך בפועל תקבלו User function not found |
התסריט הקלאסי: טופס אחד של הלקוח עובד כבר שנה, מוסיפים טופס הרשמה — ומקבלים שגיאה. הדגל הראשון דלוק, השני מעולם לא הודלק.
ב. הערך בצורה הנכונה? חייב להיות אובייקט עם המפתח הפנימי:
// ✔{ "Name": "AcceptWebToTable", "Value": { "AcceptWebToTable": true } }
// ✘ — ייקרא ככבוי{ "Name": "AcceptWebToTable", "Value": true }ג. כמה שורות יש? אם יש יותר מאחת עם אותו Name, הקוד לוקח query.first() ללא מיון — והשורה שנוצרה ראשונה מנצחת תמיד. כלומר שורה ישנה עם false תשתק בוודאות שורה חדשה עם true. מחקו כפילויות לפני שממשיכים לאבחן.
User function not found
Section titled “User function not found”שם נקודת קצה שלא קיים בשרת. שלושה מקרים:
web2lead— נתקלתם בשם הזה במדריך ישן? הפונקציה הרשומה בשרת ללכידת ליד היאgetlead. החליפו את השם — ראו getlead.web2sale/web2contact— מעולם לא היו נקודות קצה. השתמשו ב‑web2tableעם ה‑tableהמתאים.- שגיאת כתיב בשם. שימו לב: אותיות גדולות/קטנות אינן משנות (
web2Tableו‑getLeadעובדים), אבל כל שאר השם כן.
web2case כן קיימת — היא נשלטת בדגל AcceptWebToCaseLeads ומחזירה caseId במקום Id.
missing "phone"
Section titled “missing "phone"”מופיע רק ב‑web2table, בסטטוס 400. הקוד שנפרס דורש phone בפועל, גם כשנשלחו email ו‑idnum.
// ✘ יחזיר 400 {"error":"missing \"phone\""}{ "table": "Sales", "email": "israel@example.co.il", "account_Name": "ישראל" }
// ✔{ "table": "Sales", "phone": "0501234567", "email": "israel@example.co.il" }שתי סיבות אפשריות:
phoneלא נשלח בכלל — לרוב כי הטופס אוסף רק אימייל. הפתרון היחיד: להפוך את שדה הטלפון לחובה בטופס.phoneנשלח עם קידומת —account_phoneאוaccount_PhoneNumber. מפתחות האיתור הם בלי קידומת.
missing "table" in request body הוא אותו סטטוס עם סיבה אחרת: חסר שם המחלקה.
שתי תקלות table נוספות שנראות דומה אבל מחזירות משהו אחר לגמרי:
// שם מחלקה שאינו קיים{ "table": "NoSuchTable", "phone": "0501234567" }// 400 {"code":103,"message":"Class NoSuchTable does not exist."}
// התווית בעברית במקום שם המחלקה{ "table": "מכירות", "phone": "0501234567" }// 400 {"code":100,"message":"XMLHttpRequest failed: \"Request path contains unescaped characters\""}missing "PhoneNumber" or "Email"
Section titled “missing "PhoneNumber" or "Email"”ולידציה של תוכן — פעילה רק כש‑ValidatePhoneOrEmail: true יושב בתוך ה‑Value של שורת הדגל (למשל {"AcceptWebToTable": true, "ValidatePhoneOrEmail": true}) — שורת Config נפרדת בשם ValidatePhoneOrEmail לא עושה כלום. ראו Config. הגבולות, אחד־אחד:
| השדה | הכלל | דוגמאות |
|---|---|---|
| טלפון | מסירים תווים שאינם ספרות, ואז נדרשות 7–14 ספרות | 6 ספרות נדחות · 7 עוברות · 14 עוברות · 15 נדחות · 050-123-4567 ו‑+972 50-123-4567 עוברים |
| אימייל | 6–80 תווים, מכיל @ וגם . |
a@b.c (5) נדחה · a@b.co (6) עובר · 80 תווים עוברים · 81 נדחים · aaaa@bbbb (בלי נקודה) ו‑aaaabbbb.com (בלי @) נדחים |
השרת דוחה כשגם הטלפון וגם האימייל אינם תקינים. תקין אחד מהם — הבקשה עוברת (טלפון "abcdefgh" + אימייל תקין → 200).
שימו לב לסדר: phone: "" נעצר קודם ב‑missing "phone" (בדיקת הנוכחות של המפתח), גם אם האימייל תקין. הסיבה הנפוצה לשתי השגיאות: הטופס שולח מחרוזת ריקה במקום להשמיט את השדה. נקו ערכים ריקים לפני השליחה — ראו מיפוי שדות.
code 111 — schema mismatch
Section titled “code 111 — schema mismatch”{ "code": 111, "message": "schema mismatch for Accounts.LeadSourceId; expected Pointer<LeadSource> but got String" }זו שגיאת טיפוס של Parse שעולה דרך שכבת הטפסים, ושורת היעד לא נוצרת. חמש סיבות:
- Pointer באורך שאינו 10 תווים בשדה
account_*— מזהה שנחתך בהעתקה, רווח מוביל, או ערך תצוגה שנשלח במקום המזהה. (בשדהtable_*אותו ערך נזרק בשקט — ראו הסעיף הבא.) - בוליאני כמספר —
1/0במקוםtrue/false(expected Boolean but got Number). וגםaccount_IsAccountכמחרוזת. - תאריך לא מרופד —
"2026-9-1"במקום"2026-09-01"(expected Date but got String). - שדה
File/PrivateFile— אינו נתמך כלל בזרימה הזו. עם אובייקט{"__type":"File",…}השגיאה היא{"code":1}. - טיפוס שהשרת לא ממיר — למשל אובייקט מקונן בשדה מחרוזת או מספר.
// בדיקת שפיות לפני שליחה — חוסכת בקשה שנכשלת (ואיש קשר יתום)const isId = (v) => typeof v === 'string' && v.length === 10;if (data.account_LeadSourceId && !isId(data.account_LeadSourceId)) delete data.account_LeadSourceId;if (typeof data.table_IsWeb !== 'undefined') data.table_IsWeb = data.table_IsWeb === true || data.table_IsWeb === 'true';200 ושדה Pointer נשאר ריק
Section titled “200 ושדה Pointer נשאר ריק”הבקשה הצליחה, הרשומה נוצרה, השדה ריק. הסיבה תלויה בקבוצת השדה:
בשדה account_* — סיבה אחת: המזהה תקין באורכו אבל אינו קיים בטבלת ה‑lookup (מפה סטטית שנבנתה לפני שנה, וערך שנמחק מאז). במקרה כזה הערך אף נשמר כ‑Pointer שמצביע לשום מקום — השדה “ריק” רק בתצוגה. אמתו מול הטבלה עצמה — ראו מיפוי שדות.
בשדה table_* — שלוש סיבות, כולן שקטות:
- אורך שאינו 10 תווים — בניגוד ל‑
account_*, כאן זה לא 400 אלא 200 והשדה פשוט לא נכתב. - אובייקט Pointer של Parse (
{"__type":"Pointer",…}) — נזרק בשקט. שלחו מזהה חשוף. table_SaleStatusIdב‑Sales— נזרק תמיד, גם כמזהה חשוף תקין. הדרך היחידה:DefaultValues.Tableבשורת ה‑Config.
200 ושדה שנשלח פשוט לא נשמר
Section titled “200 ושדה שנשלח פשוט לא נשמר”המפתח לא קיים בסכימה. נקודות הקצה עוברות על הסכימה ומתעלמות בשקט מכל מפתח שאינו מוכר. אין שגיאה ואין אזהרה.
הסיבות, בסדר שכיחות:
- שגיאת כתיב או אותיות גדולות/קטנות —
PhonenumberבמקוםPhoneNumber,cityבמקוםCity. - שם השדה בעברית — התוויות בעברית יושבות בטבלת מערכת נפרדת ואינן שמות השדות. אין שדה בשם “טלפון”.
- דיאלקט שגוי — שם שטוח ב‑
web2table, אוaccount_ב‑getlead. - השדה באמת לא קיים אצל הלקוח הזה — קיים אצל לקוח אחר, או נמחק.
הבדיקה:
# /parse/schemas דורש Master Key — לא API Key ולא sessionToken. צד שרת בלבד.curl -sS "https://api.mbapps.co.il/parse/schemas/Accounts" \ -H "X-Parse-Application-Id: $APP_ID" -H "X-Parse-Master-Key: $MASTER_KEY" \ | python -c "import sys,json;print('\n'.join(sorted(json.load(sys.stdin)['fields'])))"// /parse/schemas דורש Master Key — לא API Key ולא sessionToken. צד שרת בלבד.const res = await fetch("https://api.mbapps.co.il/parse/schemas/Accounts", { headers: { 'X-Parse-Application-Id': APP_ID, 'X-Parse-Master-Key': MASTER_KEY, },});const schema = await res.json();console.log(Object.keys(schema.fields).sort().join('\n'));# /parse/schemas דורש Master Key — לא API Key ולא sessionToken. צד שרת בלבד.import requests
res = requests.get( "https://api.mbapps.co.il/parse/schemas/Accounts", headers={ "X-Parse-Application-Id": APP_ID, "X-Parse-Master-Key": MASTER_KEY, },)print("\n".join(sorted(res.json()["fields"])))<?php// /parse/schemas דורש Master Key — לא API Key ולא sessionToken. צד שרת בלבד.$ch = curl_init();curl_setopt_array($ch, [ CURLOPT_URL => "https://api.mbapps.co.il/parse/schemas/Accounts", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "X-Parse-Application-Id: {$APP_ID}", "X-Parse-Master-Key: {$MASTER_KEY}", ],]);$response = curl_exec($ch);curl_close($ch);$fields = array_keys(json_decode($response, true)["fields"]);sort($fields);echo implode("\n", $fields);אם אין לכם Master Key — אותה שליפה זמינה דרך כלי ה‑MCP Get-Schema עם {"className":"Accounts"}.
איש קשר חדש בכל פנייה
Section titled “איש קשר חדש בכל פנייה”הלקוח מדווח: “כל פעם שמישהו ממלא, נוצר איש קשר חדש”.
ב‑web2table — כמעט תמיד account_PhoneNumber (או account_Phone / account_Email) במקום המפתחות הלא מקודמים phone / email. הערך המקודם נשמר בשדה, אבל לא מזין את שאילתת זיהוי הכפילויות — ולכן המערכת “לא מוצאת” את איש הקשר בכל פעם.
// ✘{ table: 'Sales', account_PhoneNumber: '0501234567' }
// ✔{ table: 'Sales', phone: '0501234567' }ואל תשלחו את שניהם — phone יחד עם account_PhoneNumber הוא כפילות מיותרת.
account_PhoneNumber אכן נשמר ב‑Accounts.PhoneNumber (ואף דורס את הערך שהגיע מ‑phone), אבל לא מאתר. הווריאנט account_phone באותיות קטנות נזרק לגמרי — הוא כלל אינו שדה בסכימה.
שתי סיבות נוספות, כשהמפתחות נכונים והלקוח עדיין מוכפל — שתיהן בצד הנתונים הקיימים:
- הטלפון שמור בפורמט שאינו נסרק. השרת משווה רק מול חמישה פורמטים שמורים (
0501234567,972501234567,+972501234567,050-1234567,+972-50-1234567). איש קשר שיובא כ‑050-123-4567או050 1234567לא יאותר לעולם — גם מקלט זהה. הבדיקה: שלפו את ה‑PhoneNumberהשמור ב‑REST והשוו לרשימה. התיקון: נרמול הטבלה. - האימייל שמור באותיות אחרות. ההשוואה רגישה לאותיות:
Dana@Example.co.ilלא מתאים ל‑dana@example.co.il. התיקון: lowercase בשני הצדדים.
ראו זיהוי כפילויות.
ב‑getlead — זו התנהגות מתוכננת: הפונקציה תמיד יוצרת שורה חדשה, וכפילות מסומנת בסטטוס “ליד כפול” במקום להיחסם. אם הלקוח ציפה למיזוג — ההסבר בעמוד זיהוי כפילויות.
איש קשר קיים לא מתעדכן
Section titled “איש קשר קיים לא מתעדכן”“מילאתי את הטופס עם כתובת חדשה, והכתובת הישנה נשארה.”
זו התנהגות מתוכננת. ב‑web2table, שדות account_* מוחלים רק כשנוצר איש קשר חדש. איש קשר קיים מקושר לשורה החדשה — ולא מעודכן.
עדכון של איש קשר קיים דורש REST API בצד שרת או פונקציית שרת ייעודית. אין דרך לעשות אותו מהדפדפן, ואין מסלול עדכון אנונימי בכלל — ראו מודל האבטחה.
404 על הכתובת
Section titled “404 על הכתובת”סיבה אחת בלבד: הכתובת תחת /parse/. Cloud Functions לא יושבות שם:
✘ https://api.mbapps.co.il/parse/functions/{appId}/web2table → 404 Not Found✔ https://api.mbapps.co.il/functions/{appId}/web2tablecode 119 — CAPTCHA
Section titled “code 119 — CAPTCHA”{ "code": 119, "error": "This action is not allowed without a valid CAPTCHA" }זה לא קורה בנקודות הקצה של הטפסים — זה קורה כשמנסים לכתוב ישירות ל‑/parse/classes/<Table> עם Application Id בלבד.
התיקון: לעבור ל‑web2table. לא לפתוח CLP — שער ה‑CAPTCHA יושב לפני בדיקת ההרשאות (גם עם create: {"*": true} התשובה נשארת 119), ופתיחתן לא תעזור אבל כן תגדיל חשיפה. הפירוט: מודל האבטחה.
code 119 מופיע גם בקריאה ובעדכון, עם הודעות אחרות:
// GET /parse/classes/Sales עם App-Id בלבד{ "code": 119, "error": "Permission denied for action find on class Sales." }
// PUT /parse/classes/Sales/<objectId> עם App-Id בלבד{ "code": 119, "error": "Permission denied for action update on class Sales." }הדפדפן מדווח על CORS
Section titled “הדפדפן מדווח על CORS”CORS פתוח לנקודות הקצה האלה כברירת מחדל: preflight מחזיר 200 עם
Access-Control-Allow-Origin שמהדהד את ה‑Origin, ו‑Allow-Methods: GET,PUT,POST,DELETE,OPTIONS.
| מה שנראה כמו CORS | מה זה בעצם |
|---|---|
| נחסם בעמוד HTTPS | הקוד קורא ל‑http:// במקום https:// — זו חסימת mixed content, לא CORS |
| עובד ב‑curl ולא בדפדפן | תוסף חוסם, או iframe מוגבל (הטמעות במערכות בנייה) |
| “נכשל” בלי פרטים בקונסול | לרוב 400 עם גוף שגיאה — פתחו את לשונית Network וקראו את הגוף |
הבדיקה: הריצו את אותה בקשה ב‑curl. אם היא מחזירה 400 או 404 — הבעיה שם, לא ב‑CORS.
סדר הבדיקות המומלץ
Section titled “סדר הבדיקות המומלץ”כשמגיעה פנייה “הטופס לא עובד” בלי פרטים, זה הסדר שחוסך הכי הרבה זמן:
- הגוף, לא הסטטוס. קראו את מחרוזת ה‑
errorבתשובה — הכול חוזר כ‑400. - דגל. האם הדגל הנכון דלוק, בצורה הנכונה, בשורה אחת (והיא הישנה ביותר)? (Config)
- סכימה. האם כל שם שדה קיים בסכימה של הלקוח הזה, ובדיאלקט הנכון? (מיפוי שדות)
- פורמט. Pointer כמזהה חשוף בן 10 בדיוק (לא אובייקט), תאריך ISO שטוח מרופד, בוליאנים אמיתיים (לא
1/0), ערכים ריקים מושמטים. - CORS — אחרון, ורק אחרי ש‑curl הוכיח שהבקשה עצמה מצליחה.
מה לצרף לפנייה לתמיכה
Section titled “מה לצרף לפנייה לתמיכה”אם עברתם את ארבעת השלבים ועדיין תקוע:
- הזמן המדויק של הקריאה, כולל אזור זמן
- ה‑Application Id
- נקודת הקצה המדויקת
- גוף הבקשה המלא, בלי סודות
- קוד הסטטוס וגוף התשובה המלא
- שגיאות ופתרון תקלות — קודי השגיאה של כל שכבות ה‑API
- דגלי Config · מיפוי שדות · זיהוי כפילויות