הדף הזה אוסף את ההודעות והקודים ש-api/core מחזיר: למפתח שמסתכל בלוג, לקריאת API שנכשלה, או לסוכן שקורא לכלי. הטקסטים מובאים כפי שהם מופיעים בקוד, כדי שאפשר יהיה לחפש אותם ב-grep ולמצוא את המקור. הדף מסודר לפי רכיב, ולכל קבוצה יש טבלה של הודעה, מה גורם לה ומה עושים.
הליבה לא מגדירה מטפל שגיאות גלובלי משלה. מה שקורה ל-PHP warning או ל-fatal תלוי בהגדרות השרת (display_errors, error_log). מה שהליבה כן עושה בעצמה מתואר בסעיף הראשון.
איך שגיאות עובדות בליבה#
PHP ו-error_log#
שגיאות PHP (Fatal, Warning, Notice, Parse error) נכתבות לקובץ שמוגדר ב-error_log של PHP. הליבה גם כותבת לשם בעצמה, דרך error_log(), שורות כמו DB query failed: ... ו-503 service_unavailable: .... שתי הדרכים לקרוא את הקובץ בלי גישת שרת:
| דרך | איפה | מה היא מציגה |
|---|---|---|
פאנל error_log בניהול | /{admin}/error_log | שורות שמתחילות ב-[תאריך] ושיש בהן Fatal error, Warning, Notice או Parse error, מסוננות ומפוענחות לקובץ ושורה |
הפעולה error_log ב-agent_mcp | POST ל-agent_mcp/error_log (גם הכלי read_error_log) | שורות הקובץ הגולמיות מהנתיב של ini_get('error_log'); אם הקובץ לא קיים חוזר lines: [] עם note: error_log file not found |
הפעולה grep_logs ב-agent_mcp | חיפוש בקובץ ה-error_log וביומני הליבה | התאמות לפי pattern (חובה) |
הפאנל בניהול מזהה שורה רק לפי הצורה Fatal error: / Warning: / Notice: / Parse error:. שורות שהליבה כותבת ישירות ב-error_log(), כמו DB query failed ו-503 service_unavailable, לא נראות בו כשגיאות מסווגות. כדי למצוא אותן קוראים את הקובץ עצמו דרך read_error_log או grep_logs.
ERRORPAGE ועמוד 404#
ERRORPAGE היא מחרוזת פנימית ש-MODULE ו-AdminModule מחזירים כשאין לאן לנתב. היא לא מגיעה לגולש. MODULE::errorpage() תופס אותה, ובודק קודם אם ה-DB נכשל באמצע הבקשה: אם כן, התשובה היא 503 ולא 404 (ראו "ניתוב" למטה). אחרת הבקשה נכנסת מחדש ל-ROUTER עם הכתובת 404, ו-PAGE::$cache_this_page מכובה כדי שהעמוד לא יישמר במטמון. פירוט הזרימה בדף עמודי שגיאה ובדף מעקב ניתוב.
שגיאות DB שלא זורקות#
שאילתה שנכשלת ב-DB לא זורקת חריגה כברירת מחדל. היא מחזירה תוצאה ריקה, מגדילה את DB::$error_count, שומרת את ההודעה ב-DB::$last_error וכותבת ל-error_log. מי שצריך לדעת אם הריקנות אמיתית קורא ל-DB::had_error(). פירוט בדף דיבוג DB.
שלוש משפחות של מעטפת שגיאה ב-API#
| משפחה | מבנה | קוד HTTP | איפה |
|---|---|---|---|
| JSON-RPC | {"jsonrpc":"2.0","id":...,"error":{"code":...,"message":"..."}} | לפי המקרה (401, 403, 405) או 200 | mcp |
success / error | {"success":false,"error":"..."} | 200 כמעט תמיד, 401 ו-403 רק בשער הכניסה | agent_mcp, ai_insert_api, excel_import_api |
ok / error | {"ok":false,"error":"..."} | קוד אמיתי: 400, 401, 403, 409, 500, 502 | connector, seo_runner, perf_runner, ai_agent_runner, check_version |
בקבוצת success / error, בעיקר ב-agent_mcp, שגיאה לוגית חוזרת עם HTTP 200. לקוח שבודק רק את קוד ה-HTTP יחשוב שהקריאה הצליחה. בודקים תמיד את השדה success.
ניתוב ועמוד 404#
| הודעה או התנהגות | מקור | מה עושים |
|---|---|---|
404, העמוד 404 של האתר | MODULE::errorpage() אחרי ERRORPAGE | המודול לא נמצא או לא פעיל ב-CRM_modules, אין קובץ בקר, או שהמתודה (pname) לא ניתנת לקריאה. מפעילים מעקב ניתוב (מעקב ניתוב) ורואים באיזו הערת note הבקשה נפלה |
HTTP/1.1 503 Service Unavailable עם Retry-After: 120 | MISC::service_unavailable(), נקרא מ-MODULE::errorpage() כש-DB::had_error() | טבלאות הניתוב (seoUrl, modules) לא נקראו כי ה-DB נכשל. בודקים את ה-DB ואת error_log, לא את הכתובת |
עמוד HTML "השירות אינו זמין כרגע" (כותרת <title>: "השירות אינו זמין זמנית") | MISC::service_unavailable() | העמוד נשלח עם noindex ו-Cache-Control: no-store. הסיבה נכתבת ל-error_log בצורה 503 service_unavailable: <סיבה> ואחריה REQUEST_URI |
SERVICE UNAVAILABLE: <סיבה> ב-STDERR, יציאה עם קוד 1 | אותה פונקציה, כשרצים ב-CLI | תסריט CLI שנתקל בכשל DB. מתקנים את החיבור |
db connect (PDO): <הודעת PDO> בסיבת ה-503 | DB::connect, חיבור PDO שנכשל | פרטי החיבור ב-config (host, user, dbname). הודעת הנהג נשמרת ב-DB::$last_error |
SECURITY ERROR1 | MISC::init_security() | ערך ב-$_GET נראה כמו SQL injection לפי detect_sql_injection. בודקים את הפרמטר |
SECURITY ERROR2 | אותה פונקציה | מפתח ב-$_GET נראה כמו SQL injection |
SECURITY ERROR4 | אותה פונקציה | מפתח ב-$_POST נראה כמו SQL injection. הבדיקה של ערכי $_POST (SECURITY ERROR3) מושבתת בקוד כרגע |
ההודעות SECURITY ERROR נשלחות עם die() כטקסט פשוט, בלי עמוד ובלי קוד שגיאה מיוחד. אם אתם רואים אותן בלוג של שרת פרוקסי, זה מקורן.
על מצב mask ראו הדף מצב mask.
מסד הנתונים#
| הודעה | מקור | מה עושים |
|---|---|---|
DB query failed: <הודעת MySQL> | error_log, מ-DB::query שנכשלה | שאילתה נכשלה. ההודעה היא הודעת הנהג, למשל שם עמודה לא קיים. מוצאים את השאילתה לפי הטקסט, או מפעילים log_sql (קובץ sqllog.txt) |
<p><הודעה></p><p><השאילתה></p> מודפס בעמוד | אותו מקום, רק למנהל (ADMIN::is_admin()) | מנהל רואה את השגיאה ואת ה-SQL בתוך העמוד. גולש רגיל לא רואה כלום. זה לא קורה לגולש, ולכן "העמוד נראה תקין" לא אומר שהשאילתה הצליחה |
DB ERROR | die("DB ERROR") בענף default של switch (CONFIG::$db_type) | CONFIG::$db_type מכיל ערך שהליבה לא מכירה. התמיכה היא ב-PDO, mysql, pg ו-clickhouse |
DB::$last_error, DB::$error_count | משתנים סטטיים | לא הודעות למשתמש. אחרי שאילתה חשודה בודקים DB::had_error() |
כשרוצים שמתודה תיכשל בקול רם במקום להחזיר תוצאה ריקה, מגדירים DB::$throw_on_error = true סביב הקריאה ותופסים Throwable. כך עובד CronLogger כשהוא שומר שורת לוג.
ניהול והרשאות#
| הודעה או התנהגות | מקור | מה עושים |
|---|---|---|
הפניה (Location: /404) עם HTTP/1.1 404 Not Found | AdminModule::not_found() | אחד מארבעה: אין פאנל בשם הזה, אין לפאנל מתודה בשם ה-pname, או שאין למנהל הרשאה לפאנל, או שהפאנל מוגדר perm_developer והמנהל אינו מפתח. בניהול 404 הוא גם "אין הרשאה" |
כותרת AI-Error: <סיבה> וגוף {"error":"<סיבה>"} | אותה פונקציה, כשבבקשה יש כותרת שמתחילה ב-AI- | קריאה תכנותית (MCP, מנהל הכנסת AI) מקבלת את הסיבה במקום הפניה |
the panel '<module>' has no page called '<pname>' | סיבה ל-not_found | המתודה לא קיימת במחלקה ADMINMODULE_<module>. בודקים את שם הפעולה ב-URL |
no admin panel called '<module>' | סיבה ל-not_found | הפאנל לא רשום ב-CRM_adminPanel_panels או שאין לו מחלקה. ראו את הדף בניית פאנל |
Access denied | die("Access denied") ב-wizzo_market_api (כל הפעולות מלבד sync) ובפאנלי מדיה (newpage_media, poolse_media, target_media) | הבקשה הגיעה בלי התחברות מנהל. מתחברים לניהול |
המתקן skip_permission_check (משתנה במחלקת הפאנל) מדלג על בדיקת ההרשאה של has_perms. הוא מיועד לפאנלים שכולם צריכים לראות. פירוט בדף הרשאות.
שגיאות בכלי הניהול ב-MCP (admin_mcp_tools)#
הכלים מחזירים {"ok":false,"error":"..."} פנימית, ושכבת MCP הופכת אותה לתוצאה של הכלי. הטקסטים כאן מופיעים במלואם בקוד.
| הודעה | כלי | מה עושים |
|---|---|---|
unknown tool: <שם> | כלל הכלים | שם כלי שגוי. רשימת הכלים ב-כלי MCP |
Missing required parameter: panel | panel_schema, list_rows, save_record, set_field ועוד | חסר panel |
Missing required parameter: fields | save_record | חסר fields |
fields must be a JSON object of {column: value}, not a string, resend the same call with fields as an object | save_record | fields נשלח כמחרוזת. שולחים אובייקט |
Required parameters: panel, id, action | פעולת רשומה | חסר אחד מהשלושה |
Required parameters: panel, id | delete_record | חסר מזהה או פאנל |
no action named '<שם>' on this form right now | פעולת טופס | הפעולה לא קיימת בטופס הנוכחי של הרשומה |
panel has neither a panel_table list nor an AJAXForm | panel_schema, list_rows | הפאנל הוא עמוד מותאם אישית, אין לו טבלה או טופס שאפשר לקרוא |
panel did not return table data (custom page?) | list_rows | הפאנל החזיר עמוד מותאם ולא נתוני טבלה |
form save failed: <פירוט> | save_record | הטופס סירב לשמור. פירוט השדות ב-AI-Form-Error (ראו "טפסים") |
records is capped at 50 per call, send this batch's first 50, then the rest in the next call | set_field באצווה | שולחים עד 50 רשומות בקריאה |
records must be an array of {id, value} objects (got an unparseable string) | set_field | records לא פוענח כמערך |
each records item must be {id, value} with a positive id | set_field | פריט באצווה בלי id חיובי |
column '<שם>' is not inline-editable on this panel, update it with save_record (fields: {<שם>: ...}) instead | set_field | העמודה לא ניתנת לעריכה בשורה. משתמשים ב-save_record |
this panel does not define a delete callback | delete_record | בפאנל אין הגדרת מחיקה |
db_query is available only to admins whose group has full permissions | db_query | ההרשאה -1 (מלאה) נדרשת |
multi-statement queries are not allowed | db_query | יש ; בשאילתה |
read-only: the query must start with SELECT / SHOW / DESCRIBE / EXPLAIN | db_query | הכלי הזה לקריאה בלבד |
INTO OUTFILE / DUMPFILE is not allowed | db_query | חסום |
invalid table name | db_schema | שם טבלה עם תווים מחוץ ל-A-Za-z0-9_ |
table '<שם>' does not exist | db_schema | בתוספת similar_tables עם עד 10 הצעות |
notify_admin cap reached for this run (3) | notify_admin | מכסה של שלוש הודעות לריצה של סוכן |
remember is available only inside an agent run (וכן recall, update_playbook, claim_items) | כלי זיכרון | הכלים האלה עובדים רק בריצת סוכן |
playbook too long (<n> chars), keep it under 4000: distill and replace, don't accumulate | update_playbook | מקצרים את ה-playbook ל-4000 תווים |
התחברות#
מנהלים (admin_login, ADMIN::check_details)#
שליטה בהתחברות מנהל מחזירה טקסט פשוט, לא JSON. הקוד בצד הדפדפן קורא אותו כמחרוזת.
| תשובה | מקור | משמעות ומה עושים |
|---|---|---|
true | admin_login | הפרטים נכונים ונשלח OTP, או שאין טלפון ומייל והכניסה הושלמה |
false | admin_login | שם משתמש או סיסמה שגויים, או IP שלא ברשימת allow_ip של המנהל |
to_many_ettempts | ADMIN::check_details (הכתיב בקוד כך) | יותר מדי ניסיונות. מנהל נחסם אחרי 5 ניסיונות כושלים ב-10 דקות, ו-IP אחרי 15. ממתינים עשר דקות |
skip_otp | admin_login | למנהל מוגדר skip_otp = 1, הכניסה הושלמה בלי קוד |
error | admin_login, כשחסר username, password או phonecode, או כש-HTTP_REFERER לא ברשימת הדומיינים המותרת | בודקים שהטופס שולח את כל השדות ושהוא נטען מדומיין של האתר |
csrf_error | admin_login, כש-csrf_token נשלח ולא תקף | טוענים מחדש את מסך הכניסה לקבלת טוקן חדש |
ERROR | admin_login, אחרי אימות מוצלח אך המשתמש לא נמצא | מצב חריג. בודקים את CRM_adminPanel_admins |
declined | אימות ה-OTP | הבקשה בטלפון נדחתה, או שהזמן עבר |
invalid token, token expired or invalid, unauthorized, admin not found | מסלול כניסה עם developer_token | הטוקן חסר, פג, או שהמבקש אינו מפתח |
הכתיב to_many_ettempts שגוי בקוד ובצד הלקוח תלוי בו. מי שמשווה מחרוזות לא מתקן אותו בצד אחד בלבד.
משתמשי אתר (LOGIN)#
ל-LOGIN::login_by_details אין הודעות שגיאה: הפונקציה מחזירה false כשהמשתמש לא נמצא או שהסיסמה לא תואמת, וכשהצליחה היא מחזירה את תוצאת login_by_id (קביעת העוגיה). אין חסימת ניסיונות בשכבה הזו, זו אחריות הקוד שקורא. ראו משתמשי אתר ו-עוגיות וסשן.
טפסים#
הטפסים (Form, FormInputs) מחזירים שגיאות כטקסט שמוצג בצד הלקוח, ולבקשות תכנותיות גם בכותרת.
| הודעה | מקור | מה עושים |
|---|---|---|
שדה חובה: <כותרת השדה> | Form::mark_input_error, כששדה סימן must והחזיר ERROR | לא מילאו שדה חובה. השדה מצוין בשם הכותרת שלו |
ערך לא תקין: <כותרת השדה> | אותה פונקציה, לשדה שאינו חובה | הערך נדחה על ידי השדה. בודקים את סוג השדה |
AI-Form-Error: <JSON מקודד> | Form, רק כשיש כותרת AI-Form-Insert | אובייקט { "<שם שדה>": "<הודעה>" } בקידוד rawurlencode |
AI-New-ID: <מספר> | Form, שמירה מוצלחת של רשומה חדשה | מזהה הרשומה שנוצרה |
מחרוזת _MESSAGE_NOT_SAVED_ | Form, שמירה שנכשלה | הטקסט נלקח מטבלת המילים (LANGS::get_word), ואם המפתח חסר מוצג ריק |
_PLEASE_FILL_THE_INPUT_: <כותרת> | FormInputs, שדה חובה בצד הלקוח | מפתח שפה, ולא טקסט קבוע |
_FileTypeError_ | FormInputs, שדה קובץ | סיומת הקובץ אינה ברשימת types של השדה |
_PASSWORDS_DOSNT_MATCH_ | FormInputs, שדה סיסמה | שתי הסיסמאות לא זהות |
_secCodeError_ | FormInputs, שדה קוד אבטחה | קוד האבטחה שגוי |
_EMAIL_IS_INVALID_ | FormInputs, שדה אימייל | כתובת אימייל לא תקינה |
add_correct_phone | FormInputs, שדה טלפון | מספר טלפון לא תקין |
הודעות שנראות כמו _NAME_ הן מפתחות בטבלת langs_words ולא טקסט. הערך האמיתי תלוי בשפה, וכשמפתח חסר LANGS::get_word מחזיר מחרוזת ריקה, כך שההודעה פשוט לא תוצג. מוסיפים את המפתח דרך ניהול מילים (ראו פרמטרים ושפות).
בבדיקת סיומת בשדה קובץ הקוד קורא ל-eregi(), פונקציה שהוסרה ב-PHP 7. ב-PHP 8 העלאת קובץ דרך אותו שדה מסתיימת ב-fatal error Call to undefined function eregi() כש-$_FILES[<שם>]["name"] לא ריק. לפני שמשתמשים בשדה הזה בהעלאת קבצים בודקים אותו באתר עצמו.
אחסון והעלאות#
| הודעה | מקור | מה עושים |
|---|---|---|
STORAGE SECURITY ERROR! | STORAGE, die() | הסיומת של הקובץ ברשימה החסומה: php, pl, py, cgi, asp, perl, php3 עד php7, pht, phtml, shtml, asa, cer, asax, xap, exe, html, htm, js, css. אי אפשר לעקוף. משנים את סוג הקובץ |
STORAGE: FTP upload of <קובץ> has failed! | error_log, כשהעלאה ל-FTP נכשלת | בודקים את פרטי ה-FTP ואת מקום הדיסק בשרת האחסון |
Attempt <n>: Failed to connect to FTP server: <host> | error_log | ניסיון חיבור ל-FTP נכשל, הליבה מנסה שוב |
<h1>Cannot connect to the FTP server after multiple attempts. Please try again later.</h1> | die() אחרי כל הניסיונות | שרת ה-FTP לא עונה |
<h1>You do not have access to this ftp server!</h1> | die() | הכניסה ל-FTP נדחתה. בודקים משתמש וסיסמה בקונפיג |
false | פונקציות STORAGE רבות (תמונה לא נקראה, getimagesize נכשל, סוג קובץ לא מוכר, מזהה או hash לא תקינים) | אין הודעה. הפונקציות לא זורקות. בודקים את הערך המוחזר בכל קריאה |
פונקציות האחסון נכשלות בשקט: אין חריגה ואין כתיבה ל-error_log, מלבד שני מקרי ה-FTP. מי שמעלה קובץ חייב לבדוק את הערך שהוחזר. פירוט בדפים אחסון ו-אבטחת העלאות.
מנהל הקבצים (FileManager)#
חריגות Exception שמנהל הקבצים זורק, והפאנל file_manager מציג אותן למשתמש.
| הודעה | מה גורם לה |
|---|---|
Invalid path | נתיב ריק או עם תו null |
Path not resolvable: <נתיב> | realpath נכשל |
Not found: <נתיב> | הקובץ נדרש להתקיים ואינו קיים |
Invalid file name | שם קובץ לא חוקי ביצירה |
Parent directory does not exist | תיקיית האב לא קיימת |
Access denied, path is outside the allowed roots | הנתיב מחוץ לשורשים המותרים |
Access denied, protected file | קובץ רגיש (למשל קונפיג) |
Access denied, protected name | שינוי שם לשם של קובץ רגיש |
הפאנל במצב קריאה-בלבד (file_manager_readonly) | הפרמטר file_manager_readonly פעיל |
תיקיית core מנוהלת מרכזית, עריכה כאן תידרס בעדכון הבא | ניסיון לכתוב בתוך api/core |
CONFLICT | הקובץ שונה בשרת מאז שנפתח לעריכה |
Already exists / Target already exists / A file with that name already exists there | היעד כבר קיים |
Not a directory / Not a file / Destination is not a directory | סוג הנתיב לא מתאים לפעולה |
Cannot read directory (permission denied) / Cannot read file (permission denied) | הרשאות מערכת הקבצים |
No write permission on <תיקייה> / Write failed / Could not replace the target file / Create failed / mkdir failed / Rename failed / Copy failed / Move failed / Delete failed | כשל בכתיבה, בדרך כלל הרשאות או דיסק מלא |
Cannot move a folder into itself | העברת תיקייה לתוך עצמה |
Cannot delete a root folder | ניסיון למחוק שורש מותר |
Could not remove directory (not empty or permission denied) | תיקייה לא ריקה |
פרטים נוספים על הפאנל בדף מנהל קבצים.
MCP (mcp): שגיאות JSON-RPC#
הבקר mcp מדבר JSON-RPC 2.0 ב-POST. כל שגיאה היא {"jsonrpc":"2.0","id":<id>,"error":{"code":<קוד>,"message":"<טקסט>"}}. ה-id הוא ה-id של הבקשה, או null אם לא נשלח. הרקע וההרשמה בדף סקירת MCP.
| קוד | הודעה | HTTP | מה עושים |
|---|---|---|---|
-32700 | Parse error | 200 | גוף הבקשה אינו JSON תקין |
-32600 | Batch requests are not supported | 200 | נשלח מערך של בקשות. שולחים בקשה בודדת |
-32000 | SSE stream not supported, POST JSON-RPC messages to this endpoint | 405 | נשלח GET. משתמשים ב-POST |
-32000 | Unauthorized: send your MCP token as 'Authorization: Bearer <token>' (connect through mcp.wizzo.market: Wizzo Market > MCP) | 401 | הטוקן חסר או שגוי |
-32000 | The MCP service is not active on this site. Activate it in Wizzo Market (admin > Wizzo Market) | 403 | שירות ה-MCP לא פעיל באתר. נדרש רק לטוקן של אדם, לא לטוקן של ריצת סוכן. מפעילים בשוק (ראו סקירת השוק) |
-32602 | Unknown tool: <שם> | 200 | הכלי לא קיים |
-32602 | Tool not allowed for this token: <שם> | 200 | לטוקן אין הרשאה לכלי הזה |
-32601 | Method not found: <שיטה> | 200 | שיטת JSON-RPC שהשרת לא מממש |
הבקר מחזיר גם קודי HTTP בלי גוף: 405 ל-PUT/PATCH ושיטות אחרות, 200 ל-DELETE, 202 להודעות notifications/*.
הכלים עצמם מחזירים שגיאה כתוצאה של הכלי (ולא כשגיאת JSON-RPC), בדרך כלל עם הטקסטים שבטבלת admin_mcp_tools למעלה. כלי מותאם אישית שכותבים בעצמכם מחזיר שגיאה באותה צורה, ראו כלי MCP מותאמים.
גשר הסוכנים (agent_mcp)#
הבקר agent_mcp הוא גשר HTTP לכלי תחזוקה: שאילתות, קריאת יומנים, עדכון הליבה. הוא נגיש רק מכתובות של Wizzo ורק עם טוקן. הכתובת והטוקן הם נתוני תצורה ולא מתועדים כאן.
| תשובה | HTTP | מה גורם לה |
|---|---|---|
{"success":false,"error":"Forbidden","your_ip":...,"remote_addr":...,"forwarded_for":...} | 403 | הבקשה הגיעה מכתובת שאינה ברשימת Wizzo. התשובה מחזירה את הכתובות שהשרת ראה, לעזרה באיבחון |
{"success":false,"error":"Unauthorized"} | 401 | הטוקן חסר או שגוי. נשלח ב-Authorization: Bearer או בשדה _token |
Missing required parameter: table | 200 | פעולה שצריכה שם טבלה |
Missing required parameter: sql | 200 | פעולת query בלי sql |
Missing required parameter: pattern | 200 | grep_logs בלי תבנית |
Missing file parameter for read action | 200 | קריאת קובץ יומן בלי שם קובץ |
File not found: <שם> | 200 | קובץ היומן לא קיים |
an update is already running on this site | 200 | עדכון ליבה כבר רץ (data.busy = true). ממתינים לסיומו |
wizzo_update ended early | 200 | תהליך העדכון נעצר באמצע. הפלט נשמר ב-data, ובודקים את error_log ואת טבלת יומן העדכונים |
WizzoAI is not connected on this site | 200 | WizzoAI לא פעיל באתר |
Missing or malformed token | 200 | הפעולה admin_logout קיבלה טוקן חסר או לא בפורמט של 64 תווים הקסדצימליים |
tool is required (ובהמשכו הפניה לפעולת service_tools) | 200 | הפעולה service_call בלי שם כלי |
unknown tool: <שם> עם available | 200 | שם כלי שירות לא קיים. השדה available מונה את הקיימים |
libraries/external_mcp is missing (ובהמשכו הסבר שהליבה ישנה) | 200 | ליבה ישנה מדי שאין בה גשר השירותים החיצוניים. מעדכנים ליבה |
Server error: <הודעה> | 200 | Throwable שנתפס בפעולה |
הודעת חריגה גולמית ($e->getMessage()) | 200 | שגיאה בשאילתה או בקובץ. הטקסט הוא הודעת הנהג או ה-PHP |
agent_mcp רושם E_USER_ERROR כ-success:false עם ההודעה (רווחים מנוקים), כך שקריאות ל-trigger_error(..., E_USER_ERROR) בקוד שהגשר מריץ חוזרות כ-JSON ולא כקריסה.כלי השירותים החיצוניים (external_mcp) מתועדים בדף MCP חיצוני, ושרת הסוכנים בדף שרת סוכנים.
מחבר השוק (connector) וממשק השוק (wizzo_market_api)#
connector מחזיר {"ok":false,"error":"..."} עם קוד HTTP אמיתי. הוא מזהה את האתר לפי מפתח ה-API של השוק, ב-Authorization או ב-X-Wizzo-Key.
| הודעה | HTTP | מה עושים |
|---|---|---|
unauthorized: send the site's Wizzo Market api key as Authorization or X-Wizzo-Key | 401 | המפתח חסר או שגוי. המפתח נשמר בפרמטר של האתר ולא נכנס לקוד |
unknown action: <פעולה> | 400 | פעולה שה-connector לא מכיר |
libraries/external_mcp is missing | 500 | הליבה ישנה מדי |
<הודעת השגיאה של ההרשמה> או connect failed | 502 | החיבור לשירות החיצוני נכשל |
WizzoAI is not active on this site | 409 | WizzoAI לא מופעל בשוק |
{"ok":false,"step":"register","error":...} או register failed | 502 | ההרשמה לשירות הסוכנים נכשלה בשלב register |
libraries/OlegHosted is missing | 500 | ספריית אולג חסרה. ליבה ישנה |
אולג אינו פעיל באתר הזה | 409 | אולג לא מופעל |
libraries/SeoHosted is missing | 500 | ספריית ה-SEO המתארח חסרה |
{"ok":false,"step":"<שלב>","error":...} או migrate failed | 502 | מעבר למצב מתארח נכשל בשלב שצוין בשדה step |
wizzo_market_api מוגן אחרת:
| תשובה | HTTP | הסבר |
|---|---|---|
{"ok":false} | 403 | הפעולה sync נקראה עם מפתח שלא תואם |
Access denied | 200 | כל פעולה אחרת בלי התחברות מנהל |
פירוט נוסף בדפים סקירת השוק ו-קטלוג שירותים.
בקרי ריצה: cron ו-SEO#
cron_runner#
| תשובה | מה גורם לה |
|---|---|
ERROR: invalid or missing token | הפרמטר tk חסר או שונה מהפרמטר cron_runner_token. הרצת משימה בודדת מתירה גם מנהל מחובר |
ERROR: missing id | הרצת משימה בודדת בלי id |
ERROR: cron not found | אין משימה עם ה-id |
ERROR: empty url | למשימה אין כתובת להרצה |
CronLogger סורק את הפלט של כל משימה כדי לקבוע סטטוס ביומן: פלט שמתחיל ב-ERROR, או שיש בו Fatal error או Uncaught , מסומן error, וכל השאר ok. לכן משימה שרוצה להיכשל בצורה גלויה מחזירה פלט שמתחיל ב-ERROR. ראו קרון.
seo_runner, perf_runner, ai_agent_runner#
הבקרים האלה נקראים על ידי המנוע החיצוני או על ידי מנהל, ומחזירים {"ok":false,"error":"..."}.
| הודעה | HTTP | בקר | מה עושים |
|---|---|---|---|
unauthorized | 401 | seo_runner, perf_runner, ai_agent_runner | חתימת המנוע שגויה או חסרה |
admin or engine only | 403 | seo_runner, perf_runner | הקריאה לא ממנהל מחובר ולא מהמנוע |
admin or stream only | 403 | ai_agent_runner | כמו לעיל |
unknown action: <פעולה> | 400 | perf_runner | פעולה לא מוכרת |
bad z envelope | 400 | perf_runner | מעטפת הנתונים אינה תקינה |
agent slug missing | 200 | ai_agent_runner | חסר מזהה סוכן |
unknown run | 200 | ai_agent_runner | מזהה ריצה שלא קיים |
bad json / missing run_secret | 200 | ai_agent_runner | גוף הבקשה פגום או חסר סוד ריצה |
the stream did not import | 200 | ai_agent_runner | ייבוא תוצאות מהזרם נכשל |
חסר מזהה ממצא | 200 | seo_runner | חסר key של ממצא |
הממצא לא נמצא | 200 | seo_runner | מפתח שאינו קיים |
לא נבחר פאנל תוכן (עם need_panel: true ו-panels) | 200 | seo_runner | צריך לבחור פאנל תוכן לפני יצירת הצעות |
לממצא הזה אין מסלול הצעות אוטומטי | 200 | seo_runner | סוג הממצא לא תומך בהצעות אוטומטיות |
יצירת ההצעות נכשלה: <פירוט>, קריאת ההצעות נכשלה: <פירוט>, ההחלה נכשלה: <פירוט>, השחזור נכשל: <פירוט>, הדחייה נכשלה: <פירוט>, שמירת הפאנל נכשלה: <פירוט>, פתיחת הטיקט נכשלה: <פירוט> | 200 | seo_runner | חריגה בשלב המתואר. הפירוט הוא הודעת החריגה, ובודקים אותה ב-error_log |
רק ממצאי תוכן משוגרים לסוכן. תקלות קוד הולכות לטיקט | 200 | seo_runner | שיגור לסוכן מתאים רק לממצא ברמת שורה (scope = row) |
סוכן כבר עובד על הממצא הזה | 200 | seo_runner | כבר רץ סוכן על אותו ממצא |
הסוכן כבר סיים. הכתיבות שלו ממתינות לאישורכם בפאנל הסוכנים | 200 | seo_runner | יש כתיבות שמחכות לאישור |
הרקע לפי נושא: חבילת SEO, ממצאי SEO, מפתחים, סוכני AI ו-בריאות וביצועים.
גרסאות ועדכון (check_version, wizzo_update, core_ping)#
check_version#
| תשובה | מה גורם לה | מה עושים |
|---|---|---|
{"ok":false,"error":"forbidden"} עם HTTP 403 | הפעולה promote, כשהקורא אינו מורשה (bot_ok) | הפעולה למאסטר ולמערכת הפרסום בלבד |
bad_version | מחרוזת גרסה שלא עומדת בתבנית | שולחים גרסה בפורמט 5.0.75 |
only_latest_can_be_frozen (עם latest) | ניסיון להקפיא גרסה שאינה האחרונה | מקפיאים רק את האחרונה |
cannot_freeze_zip | בניית ה-ZIP של ההקפאה נכשלה | בודקים הרשאות כתיבה ותמיכה ב-ZipArchive |
Cannot build '<נתיב>' | בניית קובץ ה-ZIP נכשלה | דיסק מלא או הרשאות |
github_token_missing | חסר טוקן GitHub להפקת רשימת שינויים | מגדירים את טוקן GitHub של האתר |
github_401_token_expired | הטוקן פג | מחליפים טוקן |
github_rate_limited | מגבלת קצב של GitHub (403 או 429) | ממתינים |
עדכון הליבה (wizzo_update)#
הסיבות לכישלון נרשמות בעמודה error_text של יומן העדכונים ומוחזרות גם ב-agent_mcp. הפונקציה עצמה מחזירה למסך true או false.
| סיבה | משמעות ומה עושים |
|---|---|
master_unreachable | המאסטר לא ענה. בודקים רשת יוצאת מהשרת |
master_bad_json / master_not_json | המאסטר החזיר משהו שאינו JSON |
master_error (או הטקסט שהמאסטר החזיר) | שגיאה מהמאסטר |
php_too_old <גרסה> < <רצפה> | גרסת ה-PHP נמוכה מהרצפה של הליבה החדשה. משדרגים PHP לפני העדכון |
no_zip_extension | תוסף ZipArchive חסר |
disk_full <x>MB < <y>MB | אין מספיק מקום לגיבוי ולהחלפה. מפנים דיסק |
db_unreachable | ה-DB לא ענה לפני ההחלפה |
zip_download_failed <url> | הורדת ה-ZIP נכשלה |
zip_checksum_mismatch | סכום הביקורת לא תואם. לא מחליפים כלום |
cannot_open_zip / broken_extraction | הארכיון פגום או שהחילוץ נכשל |
swap_out_failed / swap_in_failed | החלפת תיקיית הליבה נכשלה. בודקים הרשאות כתיבה בתיקיית האב של הליבה |
postflight_failed <סיבה> ובסופו (rolled back to <גרסה>) או (ROLLBACK FAILED) | הבדיקה אחרי ההחלפה נכשלה. סיבות אפשריות: http_<קוד> (500 ומעלה), bad_ping <טקסט>, db_after_swap, version_mismatch <גרסה>. אם כתוב ROLLBACK FAILED חייבים התערבות ידנית |
ROLLBACK FAILED פירושו שהליבה החדשה נכשלה בבדיקה והחזרת הישנה לא הצליחה. האתר עלול להיות במצב לא תקין. מעיינים בתיקיית הגיבויים בשורש האתר ומשחזרים ידנית. הנחיות בדף עדכונים.אם עדכון גרסה נכשל עם אזהרה של ZipArchive, הסיבה הנפוצה היא דיסק מלא (disk_full), לא קוד שבור. בודקים קודם את מקום הדיסק, ובעיקר את תיקיית הגיבויים.
core_ping#
core_ping מחזיר JSON עם ok, db ו-version, וה-postflight של העדכון נשען עליו: ok שאינו אמת נחשב bad_ping, ו-db ריק נחשב db_after_swap.
מה לבדוק כשמשהו נכשל#
- מוצאים את הטקסט המדויק של ההודעה, ומחפשים אותו בקוד:
grep -rn "<טקסט>" api/core. - קוראים את
error_logדרךread_error_logאו דרך הקובץ עצמו, ולא רק דרך פאנלerror_log(ראו האזהרה בסעיף הראשון). - אם נראה שהעמוד חסר, מפעילים מעקב ניתוב (מעקב ניתוב) לפני שחושדים בקוד.
- אם ה-DB חשוד, בודקים
DB::had_error()ו-DB::$last_error, ומפעיליםlog_sql. - בקריאת API בודקים את משפחת המעטפת (
success,okאו JSON-RPC) ואת קוד ה-HTTP, ובקבוצתsuccessגם את גוף התשובה.