Skip to content

frontend: guard against null disabledProducts in Footer#1963

Open
jcristau wants to merge 1 commit into
mozilla-releng:mainfrom
jcristau:disabledproducts-not-null
Open

frontend: guard against null disabledProducts in Footer#1963
jcristau wants to merge 1 commit into
mozilla-releng:mainfrom
jcristau:disabledproducts-not-null

Conversation

@jcristau
Copy link
Copy Markdown
Contributor

@jcristau jcristau commented May 7, 2026

When the disabled-products API call errors, useAction returns { data: null }, which then propagated into state and caused "right-hand side of 'in' should be an object, got null" at render time. Default to an empty object so the in check stays valid.

This can happen e.g. on localdev if the self-signed cert for the public endpoint is rejected by the browser.

When the disabled-products API call errors, useAction returns
`{ data: null }`, which then propagated into state and caused
"right-hand side of 'in' should be an object, got null" at render
time. Default to an empty object so the `in` check stays valid.

This can happen e.g. on localdev if the self-signed cert for the public
endpoint is rejected by the browser.
@jcristau jcristau requested a review from a team as a code owner May 7, 2026 02:14
Copy link
Copy Markdown
Contributor

@Eijebong Eijebong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx

export default function Footer() {
const location = useLocation();
const group = new URLSearchParams(location.search).get('group') || 'firefox';
const [disabledProducts, setDisabledProducts] = useState([]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat unrelated but might be worth a follow up to set that to {} by default. I think it's not creating any issue because the only use is product.product in disabledProducts && disabledProducts[product.product].includes(pb.branch) and it behaves the same (and thus gets short circuited):

> "a" in []
false
> "a" in {}
false

@jcristau
Copy link
Copy Markdown
Contributor Author

As a side note we may want some explicit message/marker in the UI when access to the public api doesn't work, like we have for admin. Before this patch it's a js type error, after this patch the footer with the automated releases status is just silently broken.

@Eijebong
Copy link
Copy Markdown
Contributor

Yeah, should be fairly easy, just dupe the __heartbeat__ call for the backend to the public backend?

const [backendStatus, checkBackendStatus] = useAction(() =>
axios.get('/__heartbeat__'),
);
useEffect(() => {
if (isReady) {
checkBackendStatus();
}
}, [isReady]);
if (!isReady || backendStatus.loading) {
return (
<BrowserRouter>
<Dashboard disabled>
<Box style={{ textAlign: 'center' }}>
<CircularProgress />
</Box>
</Dashboard>
</BrowserRouter>
);
}
if (backendStatus.error) {
return (
<BrowserRouter>
<Dashboard disabled>
<ErrorPanel
error={`Error contacting Shipit backend: ${backendStatus.error.toString()}. Are you connected to the VPN?`}
/>
</Dashboard>
</BrowserRouter>
);
}

Can probably factor a bit, and skip isReady since you don't need a token to check. (name is a bit misleading I guess, that has to do with the auth0 token being there and valid)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants