[{"data":1,"prerenderedAt":1042},["ShallowReactive",2],{"blog-uk-supabase-single-row-error":3,"blog-index-uk":511},{"id":4,"title":5,"body":6,"category":468,"cover":469,"coverAlt":470,"description":471,"draft":472,"extension":473,"faq":474,"image":490,"keywords":491,"meta":499,"navigation":500,"ogTitle":501,"path":502,"published":503,"seo":504,"stem":505,"tldr":506,"updated":503,"__hash__":510},"blog_uk\u002Fblog\u002Fsupabase-single-row-error.md","Supabase \"multiple (or no) rows returned\" майже завжди означає нуль",{"type":7,"value":8,"toc":454},"minimark",[9,13,16,27,43,48,51,54,61,65,72,95,101,110,136,140,146,163,173,176,180,183,192,195,201,204,211,215,218,249,252,260,264,269,272,278,284,288,291,294,297,301,309,314,330,335,344,348,354,363,378,388,405,409,441],[10,11,12],"p",{},"Ваш застосунок каже комусь, що запис не знайдено. Ви відкриваєте Supabase Table\nEditor, і запис лежить саме там, у таблиці, з правильним id.",[10,14,15],{},"Ось що повернулося з бази:",[17,18,23],"pre",{"className":19,"code":21,"language":22},[20],"language-text","{\n  \"code\": \"PGRST116\",\n  \"message\": \"JSON object requested, multiple (or no) rows returned\",\n  \"details\": \"Results contain 0 rows, application\u002Fvnd.pgrst.object+json requires 1 row\"\n}\n","text",[24,25,21],"code",{"__ignoreMap":26},"",[10,28,29,30,34,35,38,39,42],{},"Ось частина, яку інструкція за інструкцією подає хибно: ",[31,32,33],"strong",{},"нуль рядків це\nвідповідь, яку можуть дати ваші власні правила, і читається вона точно як дані,\nщо зникли."," Пошукайте це повідомлення, і вам скажуть замінити ",[24,36,37],{},".single()"," на\n",[24,40,41],{},".maybeSingle()",". Помилка справді припиниться. Про те, чи рядка бракувало, чи\nваш відвідувач ніколи не мав права його бачити, це не каже нічого, а ці два\nвипадки лагодять по-різному.",[44,45,47],"h2",{"id":46},"що-означає-json-object-requested-multiple-or-no-rows-returned","Що означає \"JSON object requested, multiple (or no) rows returned\"?",[10,49,50],{},"Ваш запит попросив у бази рівно один рядок, а в результаті була інша кількість.\nМайже завжди ця кількість нульова.",[10,52,53],{},"Уявіть читальну залу, де ви заповнюєте бланк, а хтось за стійкою йде по книжку.\nНа вашому бланку написано: принесіть одну книжку з цим номером. Стійка\nповертається і каже, що за цим бланком нічого немає. Це єдина відповідь, яку\nдає стійка, і вона однакова, чи книжки ніколи не було в каталозі, чи вона стоїть\nна полиці, до якої у вас немає допуску. Ніхто з вами не грається. Систему\nбланків збудували так, щоб те, до чого у вас немає допуску, просто не з'являлося\nу вашому погляді на каталог.",[10,55,56,57,60],{},"Бланк тримає саме ваш застосунок, а кількість, з якою повернулася стійка,\nзаписана в рядку ",[24,58,59],{},"details"," відповіді.",[44,62,64],{"id":63},"два-різні-повідомлення-і-той-самий-код-помилки","Два різні повідомлення, і той самий код помилки",[10,66,67,68,71],{},"Код сталий, а речення ні, тож орієнтуйтеся на ",[24,69,70],{},"PGRST116",".",[10,73,74,75,78,79,81,84,85,88,89,91,92,71],{},"Для цієї однієї помилки в обігу є два формулювання, і яке ви побачите, залежить\nвід того, яку версію PostgREST тримає ваш проєкт. PostgREST це сервер, який\nперетворює ваші таблиці Supabase на HTTP API, з яким розмовляє ваш застосунок.\nЙого документація для версії 12 подає повідомлення\n",[24,76,77],{},"JSON object requested, multiple (or no) rows returned",", із рядком ",[24,80,59],{},[24,82,83],{},"Results contain 0 rows, application\u002Fvnd.pgrst.object+json requires 1 row",". У\nверсіях 13 і 14 ту саму ситуацію задокументовано як\n",[24,86,87],{},"Cannot coerce the result to a single JSON object",", а ",[24,90,59],{}," читається як\n",[24,93,94],{},"The result contains 0 rows",[10,96,97,98,100],{},"Старіше речення має друге життя поза старими проєктами. Коли ви кличете\n",[24,99,41],{}," і збігається більше ніж один рядок, JavaScript-клієнт Supabase\nпише помилку сам, замість передати її від сервера, і повідомлення, яке він\nпише, це старіше формулювання. Тож перше речення досі приходить у застосунки,\nбаза яких надіслала б друге.",[10,102,103,104,106,107,109],{},"Не рухається код. Таблиця помилок PostgREST подає ",[24,105,70],{}," під 406 в усіх\nтрьох версіях, з тим самим описом: більше ніж один рядок або жодного, коли\nпросили рівно один. Читайте поле ",[24,108,24],{}," і не зважайте на текст.",[111,112,114],"callout",{"type":113},"warn",[10,115,116,119,120,123,124,127,128,131,132,135],{},[31,117,118],{},"Якщо ви звіряєте повідомлення як рядок у власному коді, звіряйте натомість\nкод."," Блок ",[24,121,122],{},"catch",", який міряє ",[24,125,126],{},"error.message"," проти\n",[24,129,130],{},"'JSON object requested, multiple (or no) rows returned'",", працює сьогодні й\nперестає працювати того дня, коли ваш проєкт перейде на новіший PostgREST, без\nжодного вашого деплою між тим. ",[24,133,134],{},"error.code === 'PGRST116'"," це переживає.",[44,137,139],{"id":138},"чому-single-це-взагалі-створює","Чому .single() це взагалі створює",[10,141,142,143,145],{},"Бо ",[24,144,37],{}," це вказівка про форму відповіді, а не фільтр по даних.",[10,147,148,149,151,152,155,156,159,160,71],{},"Коли ви пишете ",[24,150,37],{},", клієнт Supabase додає до запиту один заголовок:\n",[24,153,154],{},"Accept: application\u002Fvnd.pgrst.object+json",". Цей заголовок просить базу надіслати\nрядок окремо, як запис. Саме він дозволяє вашому коду писати ",[24,157,158],{},"data.name"," там, де\nінакше довелося б писати ",[24,161,162],{},"data[0].name",[10,164,165,166,168,169,172],{},"База дотримується цього суворо. Один рядок іде назад як запис. Будь-яку іншу\nкількість рядків у такій формі надіслати неможливо, тож відповідь це 406 і\nоб'єкт помилки. Приберіть ",[24,167,37],{},", і той самий запит поверне ",[24,170,171],{},"[]"," із 200 і\nбез жодної помилки.",[10,174,175],{},"Тож ніщо не мусило зламатися, щоб це сталося. Порожній результат став помилкою,\nбо ваш запит сказав, що відповідь має містити рівно один запис.",[44,177,179],{"id":178},"причина-1-рядок-на-місці-а-ваші-правила-кажуть-ні","Причина 1: рядок на місці, а ваші правила кажуть ні",[10,181,182],{},"Row Level Security не відмовляє вашому запиту. Вона виймає з нього рядки, а\nвийнятий рядок ніколи не був у результаті, який рахують.",[10,184,185,186,188,189,191],{},"Row Level Security це набір правил на кожній таблиці Supabase, який рядок за\nрядком вирішує, які рядки дозволено читати конкретному відвідувачеві. Коли жодне\nправило не дозволяє вашому відвідувачеві прочитати рядок, названий вашим\nзапитом, цей рядок прибирають ще до вимірювання результату. Кількість нульова.\nВаш ",[24,187,37],{}," хотів один. Ви отримуєте ",[24,190,70],{},", і жодна частина відповіді\nне згадує, що в справі було правило.",[10,193,194],{},"Це знову читальна зала, і саме тому стійка двічі каже те саме. Ваш допуск\nзастосовують ще до того, як полицю взагалі переглянуть, тож книжка, якої вам не\nможна брати, і книжка, якої немає, дають назад однаковий бланк.",[196,197],"diagram",{"alt":198,"caption":199,"src":200},"Запит заходить зліва й розділяється на дві смуги. У верхній смузі на полиці лежить рядок, намальований бірюзовим, а смугу зупиняє бурштинова ґратка, не доходячи до полиці. У нижній смузі полиця порожня й намальована пунктиром. Обидві смуги закінчуються в одному порожньому лотку, позначеному нулем.","Рядок, прихований вашими правилами, і рядок, якого немає, однаково лишають результат порожнім. Відповідь рахує рядки, тож обидва приходять як та сама помилка.","\u002Fblog\u002Fsupabase-single-row-error\u002Ftwo-reasons-one-answer-1600x700.png",[10,202,203],{},"Саме тому Table Editor вас і збиває. SQL Editor і Table Editor у вашій панелі\nSupabase працюють з правами, на які ваші Policy не поширюються, тож вони\nпоказують вам кожен рядок. Запит вашого застосунку несе ваш publishable key і\nсесію вашого відвідувача, і на нього Policy поширюються. Два погляди на одну\nтаблицю, і лише один із них отримують ваші користувачі.",[10,205,206,207,210],{},"Цю різницю видно ззовні, і саме так ми можемо її порахувати. Наш сканер читає\nживі застосунки так, як це робив би незнайомець. За 8 435 застосунками з тих,\nяким він виставив оцінку, стоїть проєкт Supabase. На 3 680 із них питання \"чи\nможе хтось без облікового запису прочитати цю таблицю\" отримало придатну\nвідповідь, і ",[31,208,209],{},"1 584 відповіли ні",": незнайомець, що просив рядки, не отримав\nнічого. Це ніщо і є те саме ніщо, яке отримує ваш власний застосунок, коли\nжодна Policy йому не відповідає.",[44,212,214],{"id":213},"як-відрізнити-прихований-рядок-від-відсутнього","Як відрізнити прихований рядок від відсутнього",[10,216,217],{},"Виконайте той самий пошук двічі, один раз там, де Policy діють, і один раз там,\nде не діють. Один запит це вирішує.",[219,220,221,237,243],"ol",{},[222,223,224,225,228,229,232,233,236],"li",{},"Відкрийте панель Supabase, перейдіть у ",[31,226,227],{},"SQL Editor"," і візьміть рядок за тим\nсамим значенням, яке використав ваш застосунок:\n",[24,230,231],{},"select * from your_table where id = 'the-id-your-app-sent';",". Запит із SQL\nEditor іде через роль ",[24,234,235],{},"postgres",", на яку ваші Policy не поширюються.",[222,238,239,242],{},[31,240,241],{},"Якщо рядок повернувся",", він існує, і щось між вашим застосунком і рядком\nйого прибрало. Це щось є Policy, і ви в причині 1. Прочитайте Policy на тій\nтаблиці.",[222,244,245,248],{},[31,246,247],{},"Якщо й там нічого не повернулося",", рядка справді немає, і ви в причині 3\nнижче. З вашими правилами все гаразд.",[10,250,251],{},"Зробіть це перед тим, як змінювати бодай рядок коду. Обидві причини дають той\nсамий об'єкт помилки, а два ремонти не мають між собою нічого спільного.",[10,253,254,255,71],{},"Поки ви дивитеся на Policy тієї таблиці, варто знати, що вони кажуть сьогодні\nкомусь зовсім без облікового запису. Наше безкоштовне сканування читає ваш живий\nзастосунок і каже, які з ваших таблиць відповідають незнайомцеві. Воно триває\nблизько 20 секунд і не потребує облікового запису:\n",[256,257,259],"a",{"href":258},"\u002Fsecurity-scanner","просканувати застосунок",[44,261,263],{"id":262},"причина-2-повернулося-кілька-рядків","Причина 2: повернулося кілька рядків",[10,265,266,268],{},[24,267,37],{}," використали на пошуку, який може збігтися більше ніж з одним рядком.",[10,270,271],{},"Пошук за первинним ключем збігається з одним рядком або з жодним, за\nвизначенням. Пошук за поштою, за slug, за іменем, за статусом, за зовнішнім\nключем: будь-який із них може зачепити два. Звична передісторія в тому, що\nколонка тримала одне значення на рядок у ваших тестових даних і перестала це\nробити, коли прийшли справжні люди.",[10,273,274,275,277],{},"Відповідь каже вам, у якій ви причині. Обидва формулювання рядка ",[24,276,59],{},"\nназивають, скільки рядків містив результат. Нуль відсилає вас до причини 1 або\nпричини 3. Число понад нуль означає цю, і це кількість рядків, що збіглися.",[10,279,280,281,283],{},"Ремонт це не ",[24,282,41],{},". Він приймає нуль рядків і далі дає помилку на\nдвох, тож тут нічого не змінює. Або звужуйте запит до одного рядка колонкою, яка\nсправді унікальна, або прийміть, що їх кілька, і читайте список.",[44,285,287],{"id":286},"причина-3-рядка-справді-немає","Причина 3: рядка справді немає",[10,289,290],{},"Іноді рядка бракує, і запит із попереднього розділу це підтверджує.",[10,292,293],{},"Звичайні причини, у порядку, в якому вони трапляються у застосунку з vibe\ncoding. Значення, за яким фільтрував ваш запит, було порожнє, бо id ще не\nзавантажився, коли запит пішов, тож нічого не збіглося. Рядок видалили, ви самі\nабо промпт, який переписав більше, ніж ви чекали. Або запит називає таблицю,\nяку перебудували під іншою назвою, і старі рядки пішли зі старою таблицею.",[10,295,296],{},"Нічого з цього не є проблемою безпеки, і жодне не лагодиться зміною Policy. Якщо\nSQL Editor нічого не знаходить, припиніть читати про Row Level Security і\nподивіться, що передає ваш застосунок.",[44,298,300],{"id":299},"single-чи-maybesingle-чого-хоче-ваш-запит","single чи maybeSingle: чого хоче ваш запит",[10,302,303,305,306,308],{},[24,304,41],{}," там, де нічого не знайти є законною відповіддю. ",[24,307,37],{},"\nтам, де не є.",[10,310,311,313],{},[24,312,37],{}," вважає будь-яку кількість рядків, крім одного, помилкою. Це\nправильна поведінка для пошуку за первинним ключем, де нуль рядків означає, що\nзапису, про який ідеться у вашому коді, не існує, і йти далі було б гірше, ніж\nзупинитися.",[10,315,316,318,319,322,323,326,327,329],{},[24,317,41],{}," приймає нуль рядків: він віддає вам ",[24,320,321],{},"data"," як ",[24,324,325],{},"null",", без\nпомилки і з 200. Більше ніж один рядок далі є помилкою, з тим самим кодом\n",[24,328,70],{},". Тож він пасує рядкові профілю, якого могли ще не створити, або\nнеобов'язковому запису, для якого ваша сторінка малює порожній стан.",[196,331],{"alt":332,"caption":333,"src":334},"Дві смуги з підписами single і maybeSingle. У кожній смузі три клітинки, позначені 0, 1 і 2. У смузі single клітинку 1 прийнято бірюзовим, а клітинки 0 і 2 несуть бурштиновий хрестик. У смузі maybeSingle прийнято клітинки 0 і 1, а перекреслено лише клітинку 2.","Уся різниця в тому, що кожен із них робить із порожнім результатом. Два рядки відхиляють обидва, і жоден із них не змінює того, що насправді повернула база.","\u002Fblog\u002Fsupabase-single-row-error\u002Fwhat-each-one-accepts-1600x640.png",[10,336,337,338,340,341,343],{},"Одна річ, з якою треба бути обережним. Заміна ",[24,339,37],{}," на ",[24,342,41],{},"\nзмінює поведінку вашого застосунку і не змінює нічого в тому, що надіслала база.\nЯкщо рядок ховала Policy, ви перетворили видиму помилку на сторінку, що\nмалюється так, ніби запису не існує, і саме для тієї однієї людини, якій його\nтреба було побачити. Помилка вам щось казала. Робіть заміну після перевірки\nвище, коли знаєте, що нуль це чесна відповідь.",[44,345,347],{"id":346},"пильнувати-свої-правила-після-того-як-ви-їх-змінили","Пильнувати свої правила після того, як ви їх змінили",[10,349,350,353],{},[31,351,352],{},"Policy, яку ви розширюєте, щоб позбутися цієї помилки, це зміна, якої зсередини\nвашого застосунку ніхто не бачить."," Ваша власна сесія працює далі, помилки\nнемає, а чи відповідає тепер та таблиця незнайомцеві, хтось мусить піти й\nзапитати.",[10,355,356],{},[31,357,358,362],{},[256,359,361],{"href":360},"\u002Fwebsite-monitoring","Reeve Monitor"," питає це за вас:",[364,365,366,369,372,375],"ul",{},[222,367,368],{},"усі дев'ять перевірок щогодини, для трьох застосунків",[222,370,371],{},"лист того дня, коли повторне сканування оцінить ваш застосунок нижче за попереднє",[222,373,374],{},"чи відповідає застосунок, кожні 60 секунд",[222,376,377],{},"місячний звіт про побачене",[10,379,380],{},[31,381,382,383,387],{},"Правило, послаблене настільки, щоб прибрати помилку, може дати незнайомцеві\nне лише читати рядки, а й міняти їх.\n",[256,384,386],{"href":385},"\u002Fsupabase-backups","Reeve Care"," тримає копію вашої бази Supabase там, куди жодна\nзміна ваших правил не дістане.",[364,389,390,393,396,399,402],{},[222,391,392],{},"зашифрована копія щодня, збережена поза вашим обліковим записом Supabase",[222,394,395],{},"кожна копія перевірена, перш ніж її зарахувати, підрахунком рядків у кожній таблиці",[222,397,398],{},"відновлення одним кліком, яке зберігає те, що є зараз, перш ніж замінити",[222,400,401],{},"ваші завантажені файли теж, щойно ви під'єднаєте доступ до Storage",[222,403,404],{},"усе, що робить Monitor",[44,406,408],{"id":407},"що-зробити-сьогодні","Що зробити сьогодні",[410,411,412],"key-takeaways",{},[364,413,414,423,429,432,438],{},[222,415,416,417,419,420,422],{},"Орієнтуйтеся на поле ",[24,418,24],{},". ",[24,421,70],{}," приходить під двома різними реченнями, і яке дістанеться вам, залежить від версії PostgREST у вашому проєкті.",[222,424,425,426,428],{},"Читайте кількість рядків у рядку ",[24,427,59],{},". Нуль означає порожній результат. Понад нуль означає, що ваш пошук зачепив кілька рядків і потребує унікальної колонки.",[222,430,431],{},"На порожньому результаті виконайте той самий пошук у SQL Editor, перш ніж міняти код. Якщо рядок повертається там і не повертається у застосунку, його прибрала Policy.",[222,433,434,435,437],{},"Переходьте на ",[24,436,41],{},", коли знаєте, що нуль це чесна відповідь. На рядку, який ховає Policy, він замінює помилку порожньою сторінкою, без попередження.",[222,439,440],{},"Після того як ви змінили Policy, щоб цього позбутися, перевірте, що та таблиця тепер повертає комусь без облікового запису.",[10,442,443,444,448,449,453],{},"Почніть з одного запиту в SQL Editor, бо саме він вирішує, яка половина цієї\nстатті вас стосується. Якщо виявиться, що відповіддю була Policy,\n",[256,445,447],{"href":446},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","увімкнути Row Level Security на кожній таблиці","\nпоказує, як написати правило, що пропускає потрібну людину, а\n",[256,450,452],{"href":451},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","\"new row violates row-level security policy\"","\nце повідомлення, яке ви отримуєте, коли Policy відмовляє в записі, що його ви\nбачите на власні очі.",{"title":26,"searchDepth":455,"depth":455,"links":456},3,[457,459,460,461,462,463,464,465,466,467],{"id":46,"depth":458,"text":47},2,{"id":63,"depth":458,"text":64},{"id":138,"depth":458,"text":139},{"id":178,"depth":458,"text":179},{"id":213,"depth":458,"text":214},{"id":262,"depth":458,"text":263},{"id":286,"depth":458,"text":287},{"id":299,"depth":458,"text":300},{"id":346,"depth":458,"text":347},{"id":407,"depth":458,"text":408},"Основи безпеки","\u002Fblog\u002Fsupabase-single-row-error\u002Fcover-1200x630.png","Бланк замовлення і порожній лоток видачі на стійці, а позаду полиця з одним рядком, виділеним бірюзовим, за бурштиновою ґраткою.","Supabase повертає PGRST116, \"JSON object requested, multiple (or no) rows returned\", коли запит нічого не знайшов. Прихований рядок має вигляд відсутнього.",false,"md",[475,478,481,484,487],{"q":476,"a":477},"Що означає PGRST116?","Це означає, що ваш запит попросив у бази рівно один рядок, а в результаті була інша кількість. PostgREST, частина Supabase, яка відповідає вашому застосунку через HTTP, повертає це як HTTP 406 із кодом PGRST116. Кількість стоїть у рядку details відповіді, і майже завжди вона нульова.",{"q":479,"a":480},"Чому мій запит не повертає жодного рядка, хоча я бачу рядок у Supabase?","Бо SQL Editor у вашій панелі працює з правами, на які ваші Policy Row Level Security не поширюються, а ваш застосунок ні. Якщо жодна Policy не дозволяє вашому відвідувачеві читати той рядок, рядок прибирають із його результату ще до підрахунку, і назад приходить нуль. Рядок на місці. Його просто ніколи не було у відповіді.",{"q":482,"a":483},"Яка різниця між single і maybeSingle?","single() вважає будь-яку кількість рядків, крім одного, помилкою. maybeSingle() приймає нуль рядків і віддає вам data як null, без помилки, і далі повідомляє про помилку, коли збігається більше ніж один рядок. Тож maybeSingle() пасує там, де нічого не знайти є законною відповіддю, наприклад для профілю, якого ще немає, а single() пасує для пошуку за колонкою, яка може збігтися лише з одним рядком.",{"q":485,"a":486},"Чи спричиняє цю помилку Row Level Security?","Це найчастіша причина в застосунку, зробленому в Lovable, Bolt, Replit або v0. Row Level Security відфільтровує рядки з результату, а не відмовляє в запиті, тож рядок, який нікому не можна читати, не відрізнити від рядка, якого немає. Обидва дають нуль, і запит, що вимагає рівно одного рядка, падає на обох.",{"q":488,"a":489},"Чому це 406?","406 Not Acceptable це статус для запиту, на який сервер не може відповісти у тій формі, яку просили. Ваш запит ніс заголовок Accept, який казав, що відповідь має бути одним записом, а не списком, і без жодного рядка всередині немає прийнятної відповіді, яку можна надіслати. Приберіть той заголовок, і той самий запит поверне порожній список із 200.","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",[492,493,494,495,496,497,498],"json object requested multiple (or no) rows returned","pgrst116","supabase single row error","supabase single() error","406 not acceptable supabase","maybesingle supabase","supabase returns no rows but row exists",{},true,"\"Multiple (or no) rows returned\" майже завжди означає нуль","\u002Fblog\u002Fsupabase-single-row-error","2026-10-15",{"title":5,"description":471},"blog\u002Fsupabase-single-row-error",[507,508,509],"\"JSON object requested, multiple (or no) rows returned\" це помилка PGRST116, і вона означає, що ваш запит повернувся з кількістю рядків, відмінною від одного. Майже завжди ця кількість нульова.","З увімкненою Row Level Security рядок, який ваш відвідувач не має права читати, повертається як жодного рядка. Тож запис, який ви бачите в Supabase Table Editor, може бути відсутнім у вашому застосунку, хоча з даними все гаразд.","Беріть maybeSingle() там, де нічого не знайти є законною відповіддю, і single() там, де не є. Спершу виконайте один запит у SQL Editor, щоб знати, який із двох випадків у вас.","srY5aLNowUOgwx-zxkU7N4QGvn2fowHHdhcJ4Y3IILQ",[512,518,524,530,536,542,548,554,560,566,572,579,585,591,597,603,609,615,621,627,633,639,645,651,657,663,664,670,676,682,688,694,700,706,712,718,724,730,736,742,748,754,760,766,772,778,783,789,795,801,807,813,819,825,831,837,843,849,855,861,867,873,878,884,890,896,902,908,914,920,926,932,938,944,950,956,961,967,973,979,985,991,997,1003,1008,1014,1020,1026,1031,1037],{"path":513,"title":514,"description":515,"published":516,"category":468,"image":517,"draft":472},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\": пояснення","Supabase \"max client connections reached\": у пулера немає місця ще для одного клієнта. Ліміт визначає порт у вашому рядку підключення.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":519,"title":520,"description":521,"published":522,"category":468,"image":523,"draft":472},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Помилка Supabase: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\": вхід через Google вимкнено у вашому проєкті Supabase. Як увімкнути та виправити redirect_uri_mismatch.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":525,"title":526,"description":527,"published":528,"category":468,"image":529,"draft":472},"\u002Fblog\u002Fviolates-foreign-key-constraint","Помилка Supabase \"violates foreign key constraint\" під час вставки","Supabase \"insert or update on table violates foreign key constraint\": ваш рядок посилається на рядок, якого немає. Який, чому і як це виправити.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":531,"title":532,"description":533,"published":534,"category":468,"image":535,"draft":472},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Помилка Supabase \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": обовʼязковий стовпець прийшов порожнім. Звідки взявся null і як це виправити.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":537,"title":538,"description":539,"published":540,"category":468,"image":541,"draft":472},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": куди поділася сесія","\"Auth session missing!\" означає, що supabase-js не знайшла жодної сесії й навіть не спитала Supabase. Куди поділася сесія і як це виправити.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":543,"title":544,"description":545,"published":546,"category":468,"image":547,"draft":472},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","Supabase \"invalid claim: missing sub claim\": ніхто не ввійшов","\"invalid claim: missing sub claim\": Supabase Auth отримав справжній токен без жодного користувача, ключ проєкту замість сесії.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":549,"title":550,"description":551,"published":552,"category":468,"image":553,"draft":472},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"Failed to send a request to the Edge Function\": справжня причина","\"Failed to send a request to the Edge Function\": браузер не отримав відповіді, яку можна прочитати. Його консоль каже, чому, і чи ваша функція запускалася.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":555,"title":556,"description":557,"published":558,"category":468,"image":559,"draft":472},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Чому Supabase перенаправляє посилання з листів на localhost:3000","Якщо Supabase перенаправляє на localhost:3000, Site URL так і не змінили або вашої адреси немає в Redirect URLs. Як виправити і якої маски уникати.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":561,"title":562,"description":563,"published":564,"category":468,"image":565,"draft":472},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Supabase \"Email link is invalid or has expired\" на новому посиланні","На посиланні, надісланому хвилину тому, \"Email link is invalid or has expired\" у Supabase зазвичай означає, що поштовий фільтр використав його першим.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":567,"title":568,"description":569,"published":570,"category":468,"image":571,"draft":472},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\": пояснення","Supabase \"canceling statement due to statement timeout\": запит перевищив ліміт своєї ролі, 3 секунди для відвідувача. Спершу перевірте політику RLS.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":573,"title":574,"description":575,"published":576,"category":577,"image":578,"draft":472},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" у Supabase і що зникає разом","\"Database error deleting user\" у Supabase: ваша база відмовилася видаляти. Причина в логах, а виправлення вирішує, що ще буде видалено.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":580,"title":581,"description":582,"published":583,"category":468,"image":584,"draft":472},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" у Supabase","Вебхук Stripe в Edge Function Supabase пише \"No signatures found matching the expected signature\"? Причин дві. Не вимикайте перевірку.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":586,"title":587,"description":588,"published":589,"category":468,"image":590,"draft":472},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" у Supabase: три причини","Supabase відповідає \"Invalid login credentials\" на неправильний пароль, невідому пошту й акаунт Google. Як зрозуміти, що саме.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":592,"title":593,"description":594,"published":595,"category":468,"image":596,"draft":472},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": справжня помилка","\"Edge Function returned a non-2xx status code\" означає, що ваша функція Supabase відповіла помилкою. Ось де прочитати справжню.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":598,"title":599,"description":600,"published":601,"category":468,"image":602,"draft":472},"\u002Fblog\u002Fcertificate-not-trusted","Сертифікат не довірений: три причини, крім закінчення строку","Сертифікат не довірений, хоча дата в порядку? Він називає іншу адресу, підписав сам себе або в його ланцюжку бракує ланки. Як зрозуміти, що саме.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":604,"title":605,"description":606,"published":607,"category":468,"image":608,"draft":472},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","Supabase \"invalid input syntax for type uuid\": що в лапках","Supabase \"invalid input syntax for type uuid\" означає, що застосунок надіслав щось, що не є id. Прочитайте лапки, притримайте запит, залиште колонку.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":610,"title":611,"description":612,"published":613,"category":468,"image":614,"draft":472},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\": пояснення","Supabase \"duplicate key value violates unique constraint\": значення вже зайняте. Знайдіть стовпець, оберіть виправлення й сховайте значення від очей.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":616,"title":617,"description":618,"published":619,"category":468,"image":620,"draft":472},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\", хоча таблиця на місці","Supabase \"relation does not exist\" або PGRST205: жодна таблиця не має такої назви в цій схемі. Чотири перевірки, і на що зважити, відкриваючи схему.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":622,"title":623,"description":624,"published":625,"category":468,"image":626,"draft":472},"\u002Fblog\u002Fsupabase-function-not-found","Supabase PGRST202: \"Could not find the function in the schema cache\"","Supabase \"Could not find the function in the schema cache\" показує назви аргументів, які надіслав ваш застосунок. Порівняйте їх із функцією.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":628,"title":629,"description":630,"published":631,"category":468,"image":632,"draft":472},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" зазвичай означає, що назва не збігається. Чотири перевірки і рядок для перезавантаження.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":634,"title":635,"description":636,"published":637,"category":468,"image":638,"draft":472},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","Supabase \"Email Rate Limit Exceeded\": два ліміти, один код помилки","Supabase \"Email Rate Limit Exceeded\" обмежує кожен лист вашого проєкту: 2 на годину з вбудованим відправником. Що враховується і як підняти ліміт.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":640,"title":641,"description":642,"published":643,"category":468,"image":644,"draft":472},"\u002Fblog\u002Fsupabase-users-logged-out","Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 причини","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" виводить ваших користувачів із системи. Три причини і як лог Auth їх розрізняє.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":646,"title":647,"description":648,"published":649,"category":468,"image":650,"draft":472},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": три причини","Supabase \"permission denied for schema public\" означає, що бракує GRANT на схему. Що його прибрало і який рядок його повертає.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":652,"title":653,"description":654,"published":655,"category":468,"image":656,"draft":472},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": три речі, які це може означати","Supabase \"Bucket not found\" означає одне з трьох: публічне посилання на приватний бакет, неточну назву або не той проєкт.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":658,"title":659,"description":660,"published":661,"category":468,"image":662,"draft":472},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: який ключ перестав працювати?","Помилка Supabase invalid JWT — це PGRST301: підписаний токен не пройшов перевірку. У новому проєкті йдеться про сесію, а не про ключ API.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":502,"title":5,"description":471,"published":503,"category":468,"image":490,"draft":472},{"path":665,"title":666,"description":667,"published":668,"category":468,"image":669,"draft":472},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" у Supabase: де шукати","\"Database error saving new user\" означає, що щось причеплене до вашої реєстрації в Supabase впало. Справжня помилка лежить у ваших логах.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":671,"title":672,"description":673,"published":674,"category":468,"image":675,"draft":472},"\u002Fblog\u002Fwhat-is-supabase","Що таке Supabase? База даних, яку обрав ваш білдер","Що таке Supabase: база даних, вхід і сховище файлів за вашим застосунком. Supabase тримає сервери, а правила про те, хто читає ваші рядки, ваші.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":677,"title":678,"description":679,"published":680,"category":468,"image":681,"draft":472},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Відкритий у фронтенді ключ AWS це не те саме, що ключ OpenAI","Ключ доступу AWS, відкритий у вашому фронтенді, читає і пише ваше сховище. Рішення зазвичай presigned URL, а не новий ключ.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":683,"title":684,"description":685,"published":686,"category":468,"image":687,"draft":472},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" при вивантаженні","\"New row violates row-level security policy for table objects\" означає, що вашому вивантаженню бракує правила insert. Публічний бакет його не додає.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":689,"title":690,"description":691,"published":692,"category":468,"image":693,"draft":472},"\u002Fblog\u002Fbase44-security-scan","Сканування безпеки Base44: те, що бачить лише воно","Сканування безпеки Base44 перевіряє сім видів проблем зсередини. Ось половина, яку читає тільки воно, і половина, на яку воно ніколи не дивиться.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":695,"title":696,"description":697,"published":698,"category":468,"image":699,"draft":472},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Ваш API-ключ витік. Порядок дій","API-ключ витік, і ви не знаєте, що робити першим. Не кожен ключ у вашому фронтенді є витоком, а порядок важить більше за швидкість.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":701,"title":702,"description":703,"published":704,"category":468,"image":705,"draft":472},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" без вимкнення RLS","\"Infinite recursion detected in policy for relation\" означає, що ваша policy запитала таблицю, яку вона захищає. Ось як розірвати коло.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":707,"title":708,"description":709,"published":710,"category":468,"image":711,"draft":472},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" у Supabase, і хибне виправлення","\"No API key found in request\" означає, що запит дійшов до Supabase без ключа. Більшість відповідей натомість вказують на правила вашої бази.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":713,"title":714,"description":715,"published":716,"category":468,"image":717,"draft":472},"\u002Fblog\u002Fis-base44-safe","Чи безпечний Base44? Дані 5 442 застосунків","Чи безпечний Base44? Ми прогнали дев’ять перевірок на 5 442 робочих застосунках Base44. Майже всі отримали B з причин, яких власник ніколи не обирав.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":719,"title":720,"description":721,"published":722,"category":468,"image":723,"draft":472},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Сховати ключ API: перенесіть його в Supabase Edge Function","Сховати ключ API означає прибрати його з браузера, а Supabase Edge Function це найменше місце, куди його покласти. Два кроки поруч важать більше.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":725,"title":726,"description":727,"published":728,"category":468,"image":729,"draft":472},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Чи відкритий ваш файл .env? Дванадцять шляхів для перевірки","Чи відкритий ваш файл .env на вашому власному вебсервері? Дванадцять адрес скажуть це за хвилину, а влучання означає, що все в ньому вже публічне.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":731,"title":732,"description":733,"published":734,"category":468,"image":735,"draft":472},"\u002Fblog\u002Fis-v0-safe","Безпека v0: усі 1 790 просканованих застосунків v0 отримали A","Безпека v0 на 1 790 живих застосунках v0: усі отримали A. Лише 17 згадували базу даних, і саме це здебільшого вимірює оцінка A.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":737,"title":738,"description":739,"published":740,"category":468,"image":741,"draft":472},"\u002Fblog\u002Fis-bolt-safe","Чи безпечний Bolt? Що показали 1 123 застосунки Bolt","Чи безпечний Bolt? Ми прогнали 1 123 живі застосунки Bolt через дев’ять перевірок. Хостинг був чистим. Знахідки: ключі й відкриті таблиці в самих застосунках.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":743,"title":744,"description":745,"published":746,"category":468,"image":747,"draft":472},"\u002Fblog\u002Fis-supabase-down-or-your-app","Supabase не працює чи проблема у вашому застосунку? Як розрізнити","Supabase не працює чи зламався ваш застосунок? Пауза, повна база й ваша власна помилка виглядають однаково. Чотири перевірки їх розрізняють.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":749,"title":750,"description":751,"published":752,"category":468,"image":753,"draft":472},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Чи шифрує Supabase мої дані? Так. Ось від чого це захищає","Чи шифрує Supabase дані? Так: AES-256 у стані спокою, TLS під час передавання, SOC 2 та ISO 27001. Що покриває кожне і який витік не зупиняє жодне.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":755,"title":756,"description":757,"published":758,"category":468,"image":759,"draft":472},"\u002Fblog\u002Fsupabase-free-plan-limits","Ліміти безкоштовного тарифу Supabase і що стається на кожному","Ліміти безкоштовного тарифу Supabase: 500 МБ бази, 5 ГБ egress і жодних резервних копій. Що стається на кожній межі і що змінює Pro за $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":761,"title":762,"description":763,"published":764,"category":577,"image":765,"draft":472},"\u002Fblog\u002Ftest-your-supabase-backup","Перевірте резервну копію Supabase до того, як вона знадобиться","Як перевірити резервну копію Supabase: відновити в тестовий проєкт, порахувати рядки, увійти й знайти рядок, якого бракує обрізаному файлу.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":767,"title":768,"description":769,"published":770,"category":577,"image":771,"draft":472},"\u002Fblog\u002Fsupabase-backup-github-action","Безкоштовна резервна копія Supabase через GitHub Action і підступ","Резервна копія Supabase через GitHub Action безкоштовна й годиться багатьом застосункам. Робочий процес, потрібний рядок підключення та egress.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":773,"title":774,"description":775,"published":776,"category":577,"image":777,"draft":472},"\u002Fblog\u002Fdownload-your-supabase-backup","Чому ви не можете завантажити резервну копію Supabase","Завантажити резервну копію Supabase на сучасному проєкті не вийде: щоденна копія там фізична. Як це перевірити і як тримати власну копію.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":779,"title":780,"description":781,"published":776,"category":468,"image":782,"draft":472},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": бракує GRANT","З 30 жовтня нова таблиця в Supabase відповідає \"permission denied for table\", доки ви не дасте доступ. Лист показує лише половину виправлення.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":784,"title":785,"description":786,"published":787,"category":468,"image":788,"draft":472},"\u002Fblog\u002Fopen-api-endpoint-exposed","Чи є відкритий API-ендпоінт проблемою безпеки? Читайте JSON","Ваше сканування позначило відкритий API-ендпоінт. Чи це важливо, залежить від того, що повернулося, і більшість знайдених належали платформі.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":790,"title":791,"description":792,"published":793,"category":468,"image":794,"draft":472},"\u002Fblog\u002Flovable-security-scan","Сканування безпеки Lovable: чого воно не доведе","Сканування безпеки Lovable: що перевіряють Quick scan і Deep scan, коли запускається кожне, і єдине, чого не доведе жодне сканування зсередини.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":796,"title":797,"description":798,"published":799,"category":577,"image":800,"draft":472},"\u002Fblog\u002Fsupabase-backup-auth-users","Чому у вашому дампі Supabase немає користувачів","Запустіть supabase db dump окремо і отримаєте форму вашої бази та жодного її рядка, без схеми auth, у якій живуть ваші користувачі.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":802,"title":803,"description":804,"published":805,"category":468,"image":806,"draft":472},"\u002Fblog\u002Fdomain-and-certificate-expiry","Домен закінчився, сайт лежить: що буде далі","Ваш домен закінчився і сайт лежить. Ось який годинник уже пішов, чому прострочений сертифікат це менша з двох бід, і як перевірити обидва.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":808,"title":809,"description":810,"published":811,"category":468,"image":812,"draft":472},"\u002Fblog\u002Fis-lovable-safe","Чи безпечний Lovable? Що показали 18 554 застосунки Lovable","Чи безпечний Lovable? Ми прогнали 18 554 живі застосунки Lovable через дев’ять перевірок. Платформа виявилася найчистішою з п’яти. Знахідки були в застосунках.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":814,"title":815,"description":816,"published":817,"category":468,"image":818,"draft":472},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Чек-лист безпеки для vibe coding, у девʼяти перевірках","Чек-лист безпеки для vibe coding із девʼяти пунктів, кожен з яких будь-хто може перевірити у вашому живому застосунку ззовні, і кожен має тест на один рядок.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":820,"title":821,"description":822,"published":823,"category":468,"image":824,"draft":472},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Секретний ключ Stripe у фронтенді може рухати гроші","Секретний ключ Stripe, відкритий у вашому фронтенді, може повертати кошти, списувати й читати кожну картку клієнта. А ключ pk_live_ там і має бути.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":826,"title":827,"description":828,"published":829,"category":468,"image":830,"draft":472},"\u002Fblog\u002Fvite-and-next-public-env-vars","Змінні оточення Vite відкриті: префікс означає опублікувати це","Змінні оточення Vite відкриті у вашому застосунку, бо так просив префікс. VITE_ і NEXT_PUBLIC_ означають опублікувати це, а ШІ, який їх додав, не знав ціни.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":832,"title":833,"description":834,"published":835,"category":468,"image":836,"draft":472},"\u002Fblog\u002Fbase44-source-maps","Безпека Base44: що позначає скан і що з цього виправляти вам","Безпека Base44 на 5 438 просканованих застосунках: три знахідки майже на кожному належать платформі, source map є бейджем Base44, а ваша частина коротка.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":838,"title":839,"description":840,"published":841,"category":468,"image":842,"draft":472},"\u002Fblog\u002Fis-cursor-ai-safe","Чи безпечний Cursor AI? Редактор, код і опублікований застосунок","Чи безпечний Cursor AI? Три запитання в одному пошуку: що Cursor зберігає, у чому помиляється його код і чи відкритий застосунок, який ви опублікували.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":844,"title":845,"description":846,"published":847,"category":468,"image":848,"draft":472},"\u002Fblog\u002Fis-replit-safe","Чи безпечний Replit? Що ми знайшли в 3 042 живих застосунках Replit","Чи безпечний Replit? Ми прогнали 3 042 живі застосунки Replit через дев’ять зовнішніх перевірок. Знахідки були в опублікованому застосунку, а не в хостингу.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":850,"title":851,"description":852,"published":853,"category":577,"image":854,"draft":472},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: у копії бази даних немає жодного файлу","Supabase storage backup це окрема робота. Копії бази даних зберігають список ваших файлів і жодного з них, тож після відновлення кожне завантаження зламане.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":856,"title":857,"description":858,"published":859,"category":577,"image":860,"draft":472},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery у Supabase: ціна та межі","Point-in-time recovery у Supabase відмотує базу на будь-яку секунду за останній тиждень. Коштує $100 на місяць понад Pro і покриває лише базу даних.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":862,"title":863,"description":864,"published":865,"category":577,"image":866,"draft":472},"\u002Fblog\u002Fsupabase-project-paused-recover","Проєкт Supabase на паузі? Ваші дані нікуди не зникли","Supabase поставив ваш проєкт на паузу після тижня без активності. Нічого не видалено, кнопка Restore стоїть поруч із назвою, і у вас є рік, щоб натиснути.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":868,"title":869,"description":870,"published":871,"category":468,"image":872,"draft":472},"\u002Fblog\u002Fsafest-ai-app-builder","Який білдер застосунків з ШІ найбезпечніший? 30 998 тестів","Який білдер застосунків з ШІ найбезпечніший? Ми просканували 30 998 живих застосунків з Lovable, Base44, Replit, v0 і Bolt. Оцінку вирішує не білдер.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":446,"title":874,"description":875,"published":876,"category":468,"image":877,"draft":472},"Увімкніть Row Level Security на кожній таблиці Supabase і перевірте","Row Level Security у Supabase без політики закриває таблицю повністю. Політика без увімкненого перемикача не робить нічого. Ось SQL, і ось перевірка.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":879,"title":880,"description":881,"published":882,"category":468,"image":883,"draft":472},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": чого не бачить попередження","Supabase позначає \"RLS disabled in public\" як помилку. Про політику читання, яка лишає вашу таблицю так само відкритою, він не каже нічого.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":885,"title":886,"description":887,"published":888,"category":468,"image":889,"draft":472},"\u002Fblog\u002Frotate-supabase-service-role-key","Як замінити злитий ключ service_role у Supabase","Supabase каже спершу закрити витік. Інші посібники кажуть міняти негайно. Що правильно, залежить від того, куди саме потрапив ваш ключ service_role.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":891,"title":892,"description":893,"published":894,"category":468,"image":895,"draft":472},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Сканери безпеки для vibe coding у порівнянні, наш теж","Найкращий сканер безпеки для vibe coding залежить від трьох питань, на які не відповідає жоден перелік функцій. Вісім інструментів і ціни.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":897,"title":898,"description":899,"published":900,"category":468,"image":901,"draft":472},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: п’ять перевірок, які зробите самі","Supabase security checker читає ваш опублікований застосунок, а не налаштування проєкту. Ось п’ять перевірок і як виконати кожну самостійно.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":903,"title":904,"description":905,"published":906,"category":468,"image":907,"draft":472},"\u002Fblog\u002Fvibe-coding-security-scanner","Сканер безпеки для vibe coding: чого не бачить скан URL","Сканер безпеки для vibe coding читає ваш робочий застосунок ззовні. Що це охоплює, чотири речі, яких він не бачить, і як читати результат.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":909,"title":910,"description":911,"published":912,"category":468,"image":913,"draft":472},"\u002Fblog\u002Fmissing-security-headers","Відсутні заголовки безпеки: коли це справді важливо","Відсутні заголовки безпеки трапляються в наших звітах найчастіше. Від чого вони захищають і коли це найменш терміновий рядок вашого звіту.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":915,"title":916,"description":917,"published":918,"category":468,"image":919,"draft":472},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Ваш ключ API OpenAI відкритий у фронтенді. Замініть його.","Ключ API OpenAI, відкритий у фронтенді, не можна прив'язати до домену. Замініть його сьогодні, перенесіть виклик на свій сервер і обмежте витрати.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":921,"title":922,"description":923,"published":924,"category":468,"image":925,"draft":472},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Ключ API у фронтенді: що насправді віддають 30 998 застосунків","Ключ API, відкритий у вашому фронтенді, зазвичай є ключем Google Maps. Ми просканували 30 998 vibe-coded застосунків і порахували, що витікає насправді.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":927,"title":928,"description":929,"published":930,"category":577,"image":931,"draft":472},"\u002Fblog\u002Fsupabase-backup-tools-compared","Інструменти резервного копіювання Supabase, і наш серед них","Чотири види інструментів резервного копіювання Supabase, що копіює кожен і коли безкоштовна GitHub Action виграє в будь-якої оплати, нашої теж.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":933,"title":934,"description":935,"published":936,"category":468,"image":937,"draft":472},"\u002Fblog\u002Freplit-secrets-explained","Як користуватися секретами в Replit і що все одно публікується","Як користуватися секретами в Replit: додати, прочитати і усунути дві причини undefined. А ще ключі, які цей інструмент не здатен зберегти в таємниці.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":939,"title":940,"description":941,"published":942,"category":577,"image":943,"draft":472},"\u002Fblog\u002Fback-up-supabase-free-tier","Резервні копії на безкоштовному тарифі Supabase без терміналу","На безкоштовному тарифі Supabase резервних копій немає: копію робите ви. Як зробити її з панелі та що втрачає шлях через CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":945,"title":946,"description":947,"published":948,"category":468,"image":949,"draft":472},"\u002Fblog\u002Fis-supabase-secure","Чи безпечний Supabase? Так. Ваш проєкт це інше питання","Чи безпечний Supabase? Платформа проходить аудити, шифрує дані й тримає пентести. Їхня документація каже, де це закінчується і починаються ваші налаштування.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":951,"title":952,"description":953,"published":954,"category":468,"image":955,"draft":472},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Де знайти API-ключі Supabase: anon, service_role і URL","URL проєкту, ключ anon і ключ service_role лежать на одній сторінці панелі. Ось де вона, і яке з чотирьох значень має бути у вашому застосунку.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":451,"title":957,"description":958,"published":959,"category":468,"image":960,"draft":472},"New row violates row-level security policy в Supabase. Що далі?","\"New row violates row-level security policy\" означає, що Supabase відмовив у записі. Швидке виправлення знову відкриває таблицю для всіх.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":962,"title":963,"description":964,"published":965,"category":468,"image":966,"draft":472},"\u002Fblog\u002Fcors-wildcard-security-risk","Чи є вайлдкард CORS ризиком для безпеки? Майже ніколи.","Чи є вайлдкард CORS ризиком для безпеки? Зазвичай це типове налаштування вашого білдера, і воно не видає нічого, що ваш сервер і так віддавав кожному.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":968,"title":969,"description":970,"published":971,"category":577,"image":972,"draft":472},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching у Supabase це не бекап. Він іде тільки вперед.","Чому branching у Supabase це не бекап: гілка стартує без ваших даних, а мердж переносить саму лише схему. Для чого він потрібен і що брати замість нього.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":974,"title":975,"description":976,"published":977,"category":577,"image":978,"draft":472},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Як відновити резервну копію Supabase, і що ламається потім","Як відновити резервну копію Supabase з панелі або з файлу дампа, що саме замінює відновлення і чому ваш застосунок може лишитися зламаним після нього.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":980,"title":981,"description":982,"published":983,"category":468,"image":984,"draft":472},"\u002Fblog\u002Fsupabase-storage-bucket-public","Ваш бакет Supabase Storage публічний. Чи це проблема?","Публічний бакет Supabase Storage означає, що той, хто має URL файлу, може його відкрити. Він не означає, що хтось може переглянути список вмісту.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":986,"title":987,"description":988,"published":989,"category":468,"image":990,"draft":472},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Чи є проблемою ключ API Google у вашому браузері?","Ключ API Google у відкритому коді сторінки наш сканер знаходить найчастіше, і зазвичай усе гаразд. Вирішує це одне безкоштовне налаштування.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":992,"title":993,"description":994,"published":995,"category":577,"image":996,"draft":472},"\u002Fblog\u002Fai-agent-deleted-my-database","ШІ-агент видалив мої дані в Supabase. Що можна відновити?","ШІ-агент видалив дані з вашої бази. Те, що ви зможете відновити, вирішилося раніше, а наступні хвилини вирішують, скільки з цього вціліє.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":998,"title":999,"description":1000,"published":1001,"category":468,"image":1002,"draft":472},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Чи може будь-хто прочитати вашу базу Supabase? 3 680 застосунків","Чи може будь-хто прочитати вашу базу даних Supabase без входу? Ми просканували 30 998 живих застосунків, зроблених ШІ-білдерами, і виміряли, як часто так.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1004,"title":1005,"description":1006,"published":1001,"category":468,"image":1007,"draft":472},"\u002Fblog\u002Fsource-maps-exposed-in-production","Відкриті source maps: ваш застосунок публікує свій вихідний код","Відкрита source map дає будь-кому прочитати оригінальний код вашого застосунку, разом із коментарями. Перевірка за 30 секунд, і що важить насправді.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1009,"title":1010,"description":1011,"published":1012,"category":468,"image":1013,"draft":472},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: це той самий anon key?","Supabase замінив anon і service_role публічними та секретними ключами. Який із них має бути у вашому застосунку, а який не має бути ніколи?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1015,"title":1016,"description":1017,"published":1018,"category":577,"image":1019,"draft":472},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Чи робить Supabase резервні копії моєї бази? Залежить від тарифу.","Чи робить Supabase резервні копії вашої бази даних? На платних тарифах щодня, на безкоштовному жодної. Як дізнатися, що у вас насправді є.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1021,"title":1022,"description":1023,"published":1024,"category":468,"image":1025,"draft":472},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security увімкнено. Таблиця досі публічна.","Увімкнути Supabase Row Level Security не означає захистити таблицю. Захищають політики, а та, що полагодила застосунок, часто впускає всіх.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1027,"title":1028,"description":1029,"published":1024,"category":577,"image":1030,"draft":472},"\u002Fblog\u002Fversion-history-is-not-a-backup","Історія версій не є резервною копією. Вона не поверне таблицю.","Lovable і Bolt ведуть історію версій вашого коду. Ваша база даних працює як окремий сервіс, тож відкат назад не поверне ваші дані.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1032,"title":1033,"description":1034,"published":1035,"category":577,"image":1036,"draft":472},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Три способи зробити резервну копію бази Supabase, і чого бракує","Панель, pg_dump і керований сервіс. Що насправді зберігає кожен спосіб, що тихо лишає осторонь і який із них переживе втрату акаунта.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1038,"title":1039,"description":1040,"published":1035,"category":468,"image":1041,"draft":472},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Які API-ключі безпечні у браузері, а які ні","Ваш ключ anon у Supabase створений, щоб бути публічним. Ключ service_role для цього не створений, і він ігнорує всі правила, які ви задали. Як їх розрізнити.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1794213654453]