You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Due for payment 2026-04-01] [$250] Chronos is now called Chat Report when you search for it, but is called Chronos when you click on it #83447
Version Number: Reproducible in staging?: Needs Reproduction (No access to chronos) Reproducible in production?: Needs Reproduction If this was caught during regression testing, add the test name, ID and link from BrowserStack: Email or phone of affected tester (no customers): Logs:https://stackoverflow.com/c/expensify/questions/4856 Expensify/Expensify Issue URL: Issue reported by:@jliexpensify Slack conversation (hyperlinked to channel name): #Expensify Bugs
Action Performed:
Search for Chronos
Notice it’s called Chat Report
Click on Chronos
See it’s still called Chronos
Expected Result:
It should be called Chronos
Actual Result:
It's called as Chat report on the first attempt
Workaround:
Unknown
Platforms:
Select the officially supported platforms where the issue was reproduced:
Please re-state the problem that we are trying to solve in this issue.
When searching for "Chronos" in the app, the search result displays "Chat Report" instead of "Chronos". However, when clicking into the result, the chat header correctly shows "Chronos".
What is the root cause of that problem?
The search/autocomplete results and the chat header use two different code paths to resolve report names, and the search path has a timing gap.
Chat header path (works correctly): HeaderView.tsx:155 calls the deprecated getReportName from ReportUtils.ts with personalDetails passed as a parameter. This bypasses derived values and computes the name directly from participant personal details via buildReportNameFromParticipantNames — correctly resolving to "Chronos".
Search/option list path (buggy): OptionsListUtils/index.ts:993 calls getReportName(report, reportAttributesDerived) from ReportNameUtils.ts:869-874, which is a simple lookup:
This first checks the pre-computed derived reportAttributes value, then falls back to the raw report.reportName field from Onyx. For 1:1 DMs, the server typically provides reportName as 'Chat Report' (the default at CONST/index.ts:1592), expecting the client to compute the actual display name from personal details.
The reportAttributes derived value system (reportAttributes.ts) does compute the correct name "Chronos" via computeReportName → buildReportNameFromParticipantNames, but there is a timing gap:
OptionsListContextProvider initializes options when a consumer mounts (via initializeOptions() at line 265)
At initialization time, reportAttributes may still be in its initial empty state ({reports: {}}) because the derived value computation is async
Without derived values, getReportName falls back to report.reportName = 'Chat Report'
After reportAttributes finishes computing, there is no effect that re-processes existing options to pick up the new names
The incremental update effects in OptionsListContextProvider (lines 111-142 for report changes, 144-177 for report action changes) include reportAttributes?.reports in their dependency arrays, but they only process reports that had actual data changes (changedReportsEntries). When reportAttributes changes independently without any report object change, these effects return early (line 118: if (changedReportKeys.length === 0) return prevOptions).
This particularly affects the Chronos DM because it's a rarely-interacted-with system bot report, so it's unlikely to receive new messages or updates that would trigger the incremental effects to re-process it with the now-available derived name.
What changes do you think we should make in order to solve the problem?
Add a dedicated effect in OptionsListContextProvider that watches reportAttributes?.reports and updates option display names (text) when the derived value provides a name that differs from what's currently stored. This should be placed after the existing incremental update effects (around line 178):
The effect should iterate over the current options, compare each option's text against the corresponding reportAttributes.reports[reportID].reportName, and re-process options where the name has changed. This ensures that when derived values complete computation (or recompute after personal details load), the search results reflect the correct names.
The key files to modify:
App/src/components/OptionListContextProvider.tsx — add the effect watching reportAttributes?.reports for name changes
What alternative solutions did you explore? (Optional)
Modify ReportNameUtils.getReportName to compute from participant names (via global personal details) when derived values aren't available and report.reportName equals DEFAULT_REPORT_NAME. This would be a localized fix but adds computation to what's designed to be a simple lookup function.
Add a hardcoded display name for Chronos similar to how Concierge is handled at ReportNameUtils.ts:845 (isConciergeChatReport → CONST.CONCIERGE_DISPLAY_NAME). This would fix only Chronos but not address the general timing issue.
The recommended approach (dedicated effect) is preferred because it fixes the general problem for all reports, not just Chronos.
Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, or @MelvinBot <your feedback> to refine this analysis.
changed the title [-]Chronos is now called Chat Report when you search for it, but is called Chronos when you click on it[/-][+][$250] Chronos is now called Chat Report when you search for it, but is called Chronos when you click on it[/+]on Feb 25, 2026
Please re-state the problem that we are trying to solve in this issue.
When searching for "Chronos" and clicking on the Chronos report, it initially displays the title as "Chat Report" instead of "Chronos". On a subsequent visit (e.g. navigating back and clicking again), the correct name "Chronos" appears.
What is the root cause of that problem?
Both getReportName and computeReportName compute the display name for 1:1 DM reports by calling buildReportNameFromParticipantNames, which internally calls getDisplayNameForParticipant for each participant. When Chronos's personal details haven't been loaded yet, getDisplayNameForParticipant returns an empty string, so buildReportNameFromParticipantNames also returns an empty string:
Concierge does not suffer from this issue because it has a dedicated check that short-circuits to CONST.CONCIERGE_DISPLAY_NAME regardless of whether personal details are loaded:
Chronos has no such special handling, so when its personal details aren't available on first load, the name resolves to 'Chat Report'.
What changes do you think we should make in order to solve the problem?
Add a CHRONOS_DISPLAY_NAME constant and add a Chronos check alongside the existing Concierge check in both getReportName (ReportUtils) and computeReportName (ReportNameUtils), using the already-existing chatIncludesChronos helper.
Proposal: Fix Chronos Showing as "Chat Report" in Search
Problem Restatement
When a user searches for "Chronos" (the scheduling bot), the search/autocomplete result shows "Chat Report" as the report name instead of "Chronos". When the user clicks into the result, the header correctly displays "Chronos". This inconsistency makes it harder to find and identify the Chronos chat.
Root Cause
The report name computation in src/libs/ReportNameUtils.ts (computeReportName) and src/libs/ReportUtils.ts (the deprecated getReportName)
have special-case handling for Concierge but not for Chronos:
For Concierge, the name is hardcoded and returned immediately, bypassing the participant name lookup. For Chronos, there is no such check so the code falls through to buildReportNameFromParticipantNames, which depends on Chronos's personal details being loaded. When personal details for Chronos haven't loaded yet (e.g., on first load or search before data is hydrated), the function returns an empty string, and the code falls back to report.reportName — which the server sets to 'Chat Report' (the default: CONST.REPORT.DEFAULT_REPORT_NAME).
This is a data-loading timing issue, once personal details load, navigation to the report shows the correct "Chronos" name, but search (which runs earlier) sees the fallback.
Proposed Fix
Mirror the Concierge special-case pattern for Chronos in both name-computation functions:
src/CONST/index.ts — add a constant:
CHRONOS_DISPLAY_NAME: 'Chronos',
src/libs/ReportNameUtils.ts — add chatIncludesChronos to the existing import from ./ReportUtils, then add after the Concierge check:
if (chatIncludesChronos(report)) {
formattedName = CONST.CHRONOS_DISPLAY_NAME;
}
src/libs/ReportUtils.ts — in the deprecated getReportName function (~line 5878), add after the Concierge check:
if (chatIncludesChronos(report)) {
formattedName = CONST.CHRONOS_DISPLAY_NAME;
}
This fix follows the exact same pattern already used for Concierge.
📣 @rbur0425! 📣
Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
Please follow these steps:
Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.
Format:
Contributor details
Your Expensify account email: <REPLACE EMAIL HERE>
Upwork Profile Link: <REPLACE LINK HERE>
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.43-3 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:
@rojiphil The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]
[Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.
Link to discussion: Not Required. The existing checklist is good enough to capture such issues.
[Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.
Regression Test Proposal Template
[BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.
Activity
melvin-bot commentedon Feb 25, 2026
Triggered auto assignment to @sonialiap (
Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.MelvinBot commentedon Feb 25, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When searching for "Chronos" in the app, the search result displays "Chat Report" instead of "Chronos". However, when clicking into the result, the chat header correctly shows "Chronos".
What is the root cause of that problem?
The search/autocomplete results and the chat header use two different code paths to resolve report names, and the search path has a timing gap.
Chat header path (works correctly):
HeaderView.tsx:155calls the deprecatedgetReportNamefromReportUtils.tswithpersonalDetailspassed as a parameter. This bypasses derived values and computes the name directly from participant personal details viabuildReportNameFromParticipantNames— correctly resolving to "Chronos".Search/option list path (buggy):
OptionsListUtils/index.ts:993callsgetReportName(report, reportAttributesDerived)fromReportNameUtils.ts:869-874, which is a simple lookup:This first checks the pre-computed derived
reportAttributesvalue, then falls back to the rawreport.reportNamefield from Onyx. For 1:1 DMs, the server typically providesreportNameas'Chat Report'(the default atCONST/index.ts:1592), expecting the client to compute the actual display name from personal details.The
reportAttributesderived value system (reportAttributes.ts) does compute the correct name "Chronos" viacomputeReportName→buildReportNameFromParticipantNames, but there is a timing gap:OptionsListContextProviderinitializes options when a consumer mounts (viainitializeOptions()at line 265)reportAttributesmay still be in its initial empty state ({reports: {}}) because the derived value computation is asyncgetReportNamefalls back toreport.reportName='Chat Report'reportAttributesfinishes computing, there is no effect that re-processes existing options to pick up the new namesThe incremental update effects in
OptionsListContextProvider(lines 111-142 for report changes, 144-177 for report action changes) includereportAttributes?.reportsin their dependency arrays, but they only process reports that had actual data changes (changedReportsEntries). WhenreportAttributeschanges independently without any report object change, these effects return early (line 118:if (changedReportKeys.length === 0) return prevOptions).This particularly affects the Chronos DM because it's a rarely-interacted-with system bot report, so it's unlikely to receive new messages or updates that would trigger the incremental effects to re-process it with the now-available derived name.
What changes do you think we should make in order to solve the problem?
Add a dedicated effect in
OptionsListContextProviderthat watchesreportAttributes?.reportsand updates option display names (text) when the derived value provides a name that differs from what's currently stored. This should be placed after the existing incremental update effects (around line 178):The effect should iterate over the current options, compare each option's
textagainst the correspondingreportAttributes.reports[reportID].reportName, and re-process options where the name has changed. This ensures that when derived values complete computation (or recompute after personal details load), the search results reflect the correct names.The key files to modify:
App/src/components/OptionListContextProvider.tsx— add the effect watchingreportAttributes?.reportsfor name changesWhat alternative solutions did you explore? (Optional)
Modify
ReportNameUtils.getReportNameto compute from participant names (via global personal details) when derived values aren't available andreport.reportNameequalsDEFAULT_REPORT_NAME. This would be a localized fix but adds computation to what's designed to be a simple lookup function.Add a hardcoded display name for Chronos similar to how Concierge is handled at
ReportNameUtils.ts:845(isConciergeChatReport→CONST.CONCIERGE_DISPLAY_NAME). This would fix only Chronos but not address the general timing issue.The recommended approach (dedicated effect) is preferred because it fixes the general problem for all reports, not just Chronos.
Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR, or@MelvinBot <your feedback>to refine this analysis.melvin-bot commentedon Feb 25, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @rojiphil (
External)[-]Chronos is now called Chat Report when you search for it, but is called Chronos when you click on it[/-][+][$250] Chronos is now called Chat Report when you search for it, but is called Chronos when you click on it[/+]melvin-bot commentedon Feb 25, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022026657268852610505
abbasifaizan70 commentedon Feb 25, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When searching for "Chronos" and clicking on the Chronos report, it initially displays the title as "Chat Report" instead of "Chronos". On a subsequent visit (e.g. navigating back and clicking again), the correct name "Chronos" appears.
What is the root cause of that problem?
Both
getReportNameandcomputeReportNamecompute the display name for 1:1 DM reports by callingbuildReportNameFromParticipantNames, which internally callsgetDisplayNameForParticipantfor each participant. When Chronos's personal details haven't been loaded yet,getDisplayNameForParticipantreturns an empty string, sobuildReportNameFromParticipantNamesalso returns an empty string:App/src/libs/ReportNameUtils.ts
Lines 160 to 193 in 7a6393d
The functions then fall back to
report?.reportName, which defaults toCONST.REPORT.DEFAULT_REPORT_NAME('Chat Report'):App/src/libs/ReportNameUtils.ts
Lines 855 to 858 in 7a6393d
App/src/libs/ReportUtils.ts
Lines 5933 to 5936 in 7a6393d
Concierge does not suffer from this issue because it has a dedicated check that short-circuits to
CONST.CONCIERGE_DISPLAY_NAMEregardless of whether personal details are loaded:App/src/libs/ReportNameUtils.ts
Lines 845 to 847 in 7a6393d
App/src/libs/ReportUtils.ts
Lines 5925 to 5927 in 7a6393d
Chronos has no such special handling, so when its personal details aren't available on first load, the name resolves to
'Chat Report'.What changes do you think we should make in order to solve the problem?
Add a
CHRONOS_DISPLAY_NAMEconstant and add a Chronos check alongside the existing Concierge check in bothgetReportName(ReportUtils) andcomputeReportName(ReportNameUtils), using the already-existingchatIncludesChronoshelper.In
src/CONST/index.ts:CONCIERGE_DISPLAY_NAME: 'Concierge', + CHRONOS_DISPLAY_NAME: 'Chronos',In
src/libs/ReportUtils.ts:if (isConciergeChatReport(report, conciergeReportID)) { formattedName = CONST.CONCIERGE_DISPLAY_NAME; } + if (chatIncludesChronos(report)) { + formattedName = CONST.CHRONOS_DISPLAY_NAME; + } + if (formattedName) {In
src/libs/ReportNameUtils.ts:+import {chatIncludesChronos} from './ReportUtils';if (isConciergeChatReport(report)) { formattedName = CONST.CONCIERGE_DISPLAY_NAME; } + if (chatIncludesChronos(report)) { + formattedName = CONST.CHRONOS_DISPLAY_NAME; + } + const isArchivedNonExpense = isArchivedNonExpenseReport(report, !!privateIsArchivedValue);Demo
rbur0425 commentedon Feb 25, 2026
Proposal: Fix Chronos Showing as "Chat Report" in Search
Problem Restatement
When a user searches for "Chronos" (the scheduling bot), the search/autocomplete result shows "Chat Report" as the report name instead of "Chronos". When the user clicks into the result, the header correctly displays "Chronos". This inconsistency makes it harder to find and identify the Chronos chat.
Root Cause
The report name computation in src/libs/ReportNameUtils.ts (computeReportName) and src/libs/ReportUtils.ts (the deprecated getReportName)
have special-case handling for Concierge but not for Chronos:
// ReportNameUtils.ts:845-847
if (isConciergeChatReport(report)) {
formattedName = CONST.CONCIERGE_DISPLAY_NAME; // 'Concierge'
}
For Concierge, the name is hardcoded and returned immediately, bypassing the participant name lookup. For Chronos, there is no such check so the code falls through to buildReportNameFromParticipantNames, which depends on Chronos's personal details being loaded. When personal details for Chronos haven't loaded yet (e.g., on first load or search before data is hydrated), the function returns an empty string, and the code falls back to report.reportName — which the server sets to 'Chat Report' (the default: CONST.REPORT.DEFAULT_REPORT_NAME).
This is a data-loading timing issue, once personal details load, navigation to the report shows the correct "Chronos" name, but search (which runs earlier) sees the fallback.
Proposed Fix
Mirror the Concierge special-case pattern for Chronos in both name-computation functions:
src/CONST/index.ts — add a constant:
CHRONOS_DISPLAY_NAME: 'Chronos',
src/libs/ReportNameUtils.ts — add chatIncludesChronos to the existing import from ./ReportUtils, then add after the Concierge check:
if (chatIncludesChronos(report)) {
formattedName = CONST.CHRONOS_DISPLAY_NAME;
}
src/libs/ReportUtils.ts — in the deprecated getReportName function (~line 5878), add after the Concierge check:
if (chatIncludesChronos(report)) {
formattedName = CONST.CHRONOS_DISPLAY_NAME;
}
This fix follows the exact same pattern already used for Concierge.
melvin-bot commentedon Feb 25, 2026
📣 @rbur0425! 📣
Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
Please follow these steps:
Format:
39 remaining items
melvin-bot commentedon Mar 25, 2026
Reviewinglabel has been removed, please complete the "BugZero Checklist".melvin-bot commentedon Mar 25, 2026
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.43-3 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:
If no regressions arise, payment will be issued on 2026-04-01. 🎊
For reference, here are some details about the assignees on this issue:
melvin-bot commentedon Mar 25, 2026
@rojiphil The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]
melvin-bot commentedon Mar 25, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)rojiphil commentedon Mar 31, 2026
BugZero Checklist:
[Contributor] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.
Link to comment
[Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.
Link to discussion: Not Required. The existing checklist is good enough to capture such issues.
[Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.
[BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.
Link to issue: https://github.com/Expensify/Expensify/issues/620115
Regression Test Proposal
Precondition:
Test:
Do we agree 👍 or 👎
Zapier Logs
Run ID: 00040eee-e145-a0ea-aa47-f1122d256854melvin-bot commentedon Apr 1, 2026
Payment Summary
Upwork Job
BugZero Checklist (@mallenexpensify)
mallenexpensify commentedon Apr 2, 2026
Payment Summary
Contributor+: @rojiphil due $250 via NewDot
^ Test case created
I think everything else is correct, comment/reopen if not (ie. if there's a regression I missed)
quinthar commentedon Apr 13, 2026
Approved $250 to @rojiphil