Miłosz Orzeł

.net, js/ts, html/css, arduino, java... no rants or clickbaits.

The Daily Grind (Quick Tips on Miscellaneous Issues, Ep. 3)

Intro

Here's a third round of random issues and quick tips for working around them. Part one is here, Part two is here.

The issues:

 

Firestore index disappearing after deploy

If you create a query that uses couple of fields, Firestore would want you to add and index to make it fast (indexes for basic queries are added automatically). To make the setup easy, Firestore checks if query index is present when a query is invoked and if index is missing, an error is dumped into browser console. The error message contains a special link to index configuration page with all fields preconfigured. Nice!

So, I have deployed a new version of app (GitHub Actions job doing firebase deploy) that used compound query. As expected, the first query call failed and I've used the provided index configuration link. After a while index was added and then the query worked. But, after the app was deployed again, the query failed on a missing index...

The issue was that during deployment, the index configuration from firestore.indexes.json file was reapplied, overriding index added by link. To make the changes permanent I needed to first add the index with a link and then run firebase firestore:indexes command to update the indexes config. With the firestore.indexes.json refreshed and saved in the repo, all indexes were available after next deploy.

 

Firestore deploy failing because "index already exists"

Normally Firestore is smart enough not to complain if you redeploy a project that doesn't make any changes to indexes. Unfortunately, suddenly, it stated to just that during a GitHub Action that used firebase deploy:

Error: Request to https://firestore.googleapis.com/v1/projects/example/databases/(default)/collectionGroups/something/indexes had HTTP Error: 409, index already exists
[2025-07-22T07:30:23.592Z] Error Context: ***
  "body": ***
    "error": ***
      "code": 409,
      "message": "index already exists",
      "status": "ALREADY_EXISTS"
    ***
  ***,
  "response": ***
    "statusCode": 409
  ***
***

This issue on GitHub is about the same problem. Yes, it's from 2019 and marked as closed but notice that it has fresh (July 2025) comments mentioning that the problem still appears. Maybe Firestore team will address it. In the meantime removing the index manually through Firestore console and triggering redeployment fixed the issue (indexes form firestore.indexes.json were recreated).

 

Deployment failing on installing Firebase CLI

GitHub Action with a step that installs firebase-tools was working just fine, then suddenly builds stated to fail with such error:

-- Setting permissions on binary... /usr/local/bin/firebase
/usr/local/bin/firebase: line 1: Not: command not found
Something went wrong, firebase has not been installed.
Please file a bug with your system information on Github.
https://github.com/firebase/firebase-tools/
-- All done!
Error: Process completed with exit code 1.

It turned out that many people were affected by the same problem and an issue on the CLI repo was raised quicky. The problem is now fixed and Firebase team offered a brief explanation (artifacts for outdated version were built). This is not the first time such CI/CD pipeline mishap happened, a workaround is suggested here.

 

MUI X Date Picker stopped informing about invalid date

Recently a project I work on was migrated from @mui/material 6.4.6 and @mui/x-date-pickers: 7.21.0 to @mui/material: 7.1.1 and @mui/x-date-pickers: 8.5.2. The migration was mostly painless... Except for one regression: suddenly validation on date field stopped rejecting incomplete inputs. It used to happen that when user removed part of date, and placeholder started to be partially visible, the validation kicked in and user was not able to progress through questionnaire. After the migration, incomplete input was simply ignored and nothing prevented user from going forward (the field is not mandatory). This is quite dangerous, it's easy for people to accidently remove part of input with complex placeholders and save the form assuming that a correct value is provided, while it is silently dropped.

The problem happens because previous version provided Invalid Date as a value to onChange handler if input was incomplete, but recent version gives null in that case. 

There's an issue about it and I'm asking MUI team to restore some easy way to recognize incomplete input. There's hope, the issue appears on a milestone.

 

Warning about unnecessary React useEffect dependency on ref

I was doing a bit of layout simplification and wanted to get rid of MUI PaperTrapFocus wrapper on certain panel and replace it with a simple Box wrapper. It all went well except that the wrapper needed to be automatically focused when screen loaded (for the sake of some keyboard event handling). Initially I've added the focus by keeping a ref to the wrapper div (the Box) and focusing it in a useEffect that depended on the ref. In this specific case it worked, but it felt a bit dirty and made React linter complain with such message:

81:6 warning React Hook useEffect has an unnecessary dependency: 'wrapperRef.current'. Either exclude it or remove the dependency array. Mutable values like 'wrapperRef.current' aren't valid dependencies because mutating them doesn't re-render the component react-hooks/exhaustive-deps

Fortunately there's a better way. In React, refs can point to functions too! All I needed was a function wrapped by useCallback hook that set the focus when wrapper element became available:

const wrapperFocusRef = useCallback((wrapper: HTMLDivElement) => {
 wrapper?.focus();
}, []);

<Box
  ref={wrapperFocusRef}
  sx={{ outline: 'none' }}
  tabIndex={-1}
  onKeyDown={handleKeyDown}
>

Check this GH comment and this older piece of docs for details.

 

Toast message unusable for copying

The app I work on uses React-Toastify, lib works well, but I noticed one annoying thing with our setup: it was difficult to select text from message. Trying to highlight part of text moved the toast on horizontal axis and reduced opacity. 

This happened becasue the draggable option was set to true in ToastContainerProps. With draggable option active, user can close the toast by sliding it across the screen. In my case this was not needed becasue messages are closable by a button.

If really necessary, the draggable could stay active on mobile devices (where swiping motion is natural) and be disabled on desktop (where selecting with mouse is natural). In Capacitor app, the decision can be made with isNativePlatform call. If disabling draggable is out of the question, some CSS tricks with .Toastify__toast and .Toastify__toast:hover classes could help (pointer-eventstransformopacity...).

The Daily Grind (Quick Tips on Miscellaneous Issues, Ep. 2)

Intro

Here's a second round of random issues and quick tips for working around them. Part one is here.

The issues:

 

Firebase app GitHub Actions deploy failing (IAM_PERMISSION_DENIED)

I've added a feature that used Firebase Cloud Storage bucket. It all worked well on emulator but when I wanted to deploy it to test environment through GitHub Actions, the job failed with such error:

Error: Request to https://firebasestorage.googleapis.com/v1alpha/projects/example-project/defaultBucket had HTTP Error: 403, Permission 'firebasestorage.defaultBucket.get' denied on resource '//firebasestorage.googleapis.com/projects/example-project/defaultBucket' (or it may not exist).

"details": [
  ***
    "@type": "type.googleapis.com/google.rpc.ErrorInfo",
    "reason": "IAM_PERMISSION_DENIED",
    "domain": "firebasestorage.googleapis.com",
    "metadata": ***
      "resource": "projects/example-project/defaultBucket",
      "permission": "firebasestorage.defaultBucket.get"
    ***
  ***
]

It happened because GitHub Action was using a service account which lacked firebasestorage.defaultBucket.get permission. The permission is listed under roles/firebasestorage.viewer, so such role should be added to the service account. 

You can see your project's service accounts in Project settings / Service account page in Firebase console and manage it on GCP IAM & Admin / IAM page (IAM stands for Identity and Access Management). My project uses Tarraform and Terragrunt so after adding the role through GCP console (for a quick test) I had to add it to .tf file and run terragrunt apply to modify all the environments...

 

SignatureDoesNotMatch error while fetching file from a bucket

I was fetching a file with unusual file extension in React app (in-house DSL that programs clinical trial questionnaires). To work correctly it needed to be recognized as text/plain MIME type instead of the default application/octet-stream. When the file was loaded from Firebase hosting, I could set 'Content-Type': 'text/plain' header while fetching. When I've tired to do the same after switching to Firestore bucket, an 403 error with SignatureDoesNotMatch in response stated to appear.

The signature feature didn't like the fetch header setting, but it was possible to go without it by setting the Content-Type property in the uploaded file metadata. To edit the metadata you can go to GCP storage browser and use Storage bucket details -> Edit metadata menu.

BTW: You might face another issue while working with cloud storage: your newly uploaded file will be reachable when opening file link in browser or by doing a GET in curl but it might fail with fetch due to lack of CORS settings. If you get this issue look here or search how to use gsutil cors set cors.json gs://your-bucket-name command.

 

No level config per handler in @datadog/browser-logs

Datadog has a pretty neat feature that allows sending logs from browser to Datadog servers (including automatic reporting of unhandled errors and rejected promises). You might want to use the http handler that sends data over network (debounced) and the console handler that forwards entries to browser's console. You can set the log level (e.g. info vs debug), but the issue is that you cannot configure different level for each handler. That's a bummer, it would be cool to use info level for logs sent over network but still see the debug logs in console...

Fortunately there is a simple workaround. The datadogLogs has beforeSend callback and you can use it to filter out debug entries:

datadogLogs.init({
  // More init props here
  beforeSend: logsEvent => {
    return logsEvent.status !== 'debug';
  },
});

const logger = datadogLogs.createLogger('example-logger', {
  level: 'debug',
  handler: ['http', 'console'],
});

 

Grep skipping hidden files (fzf-lua+ripgrep in Neovim)

I like ripgrep and fzf a lot! These are great not only as standalone command line tools, but can also be combined to provide awesome search experience in Vim/Neovim. For Vim there's a fzf.vim plugin and for Neovim I can recommend se fzf-lua.

I often use life_grep command for quick regexp search of the codebase (which can later be fine tuned by fuzzy search of files that contain a match). I have this mapping:

vim.keymap.set('n', '<leader>sg', ':FzfLua live_grep<CR>', { desc = '[s]earch live [g]rep' })

I used to have such config for the fzf-lua plugin:

require('fzf-lua').setup { 'max-perf' }

but there was an issue: grepping would skip hidden files and directories (.env files, .github folder etc.). I think it's much safer and useful to check the hidden files too, so now I'm using such config: 

require('fzf-lua').setup {
  'max-perf',
  grep = {
    rg_opts = "--hidden --glob '!.git/' --color=never --no-heading --column -n --smart-case",
  },
}

With the above, live_grep still avoids scanning the .git folder, and node_modules are still skipped due to ripgrep's sensible defaults but I won't miss occurrences in hidden files.

There's a simpler option, if you don't care about .git being included in search too:

require('fzf-lua').setup {
  'max-perf',
  grep = {
    hidden = true,
  },
}