Skip to content

[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

Closed

Description

@m-natarajan

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


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:

  1. Search for Chronos
  2. Notice it’s called Chat Report
  3. Click on Chronos
  4. 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:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari

Screenshots/Videos

Image Image

View all open jobs on GitHub

Issue OwnerCurrent Issue Owner: @mallenexpensify
Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~022026657268852610505
  • Upwork Job ID: 2026657268852610505
  • Last Price Increase: 2026-03-04

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Feb 25, 2026
  2. melvin-bot commented on Feb 25, 2026

    @melvin-bot

    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.

  3. MelvinBot commented on Feb 25, 2026

    @MelvinBot
    Contributor

    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: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:

    reportAttributesDerivedValue?.[report.reportID]?.reportName ?? report.reportName ?? ''
    

    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:

    1. OptionsListContextProvider initializes options when a consumer mounts (via initializeOptions() at line 265)
    2. At initialization time, reportAttributes may still be in its initial empty state ({reports: {}}) because the derived value computation is async
    3. Without derived values, getReportName falls back to report.reportName = 'Chat Report'
    4. 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)

    1. 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.

    2. 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.

  4. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Feb 25, 2026
  5. added
    Help WantedApply this label when an issue is open to proposals by contributors
    on Feb 25, 2026
  6. melvin-bot commented on Feb 25, 2026

    @melvin-bot

    Triggered auto assignment to Contributor-plus team member for initial proposal review - @rojiphil (External)

  7. 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
  8. melvin-bot commented on Feb 25, 2026

    @melvin-bot
  9. abbasifaizan70 commented on Feb 25, 2026

    @abbasifaizan70
    Contributor

    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 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:

    const buildReportNameFromParticipantNames = ({
    report,
    personalDetailsList: personalDetailsData,
    currentUserAccountID,
    }: {
    report: OnyxEntry<Report>;
    personalDetailsList?: Partial<PersonalDetailsList>;
    currentUserAccountID?: number;
    }) =>
    Object.keys(report?.participants ?? {})
    .map(Number)
    .filter((id) => id !== currentUserAccountID)
    .slice(0, 5)
    .map((accountID) => ({
    accountID,
    name: getDisplayNameForParticipant({
    accountID,
    shouldUseShortForm: true,
    personalDetailsData,
    formatPhoneNumber: formatPhoneNumberPhoneUtils,
    }),
    }))
    .filter((participant) => participant.name)
    .reduce((formattedNames, {name, accountID}, _, array) => {
    // If there is only one participant (if it is 0 or less the function will return empty string), return their full name
    if (array.length < 2) {
    return getDisplayNameForParticipant({
    accountID,
    personalDetailsData,
    formatPhoneNumber: formatPhoneNumberPhoneUtils,
    });
    }
    return formattedNames ? `${formattedNames}, ${name}` : name;
    }, '');

    The functions then fall back to report?.reportName, which defaults to CONST.REPORT.DEFAULT_REPORT_NAME ('Chat Report'):

    // Not a room or PolicyExpenseChat, generate title from first 5 other participants
    formattedName = buildReportNameFromParticipantNames({report, personalDetailsList, currentUserAccountID});
    const finalName = formattedName ?? report?.reportName ?? '';

    App/src/libs/ReportUtils.ts

    Lines 5933 to 5936 in 7a6393d

    currentParent = getParentReport(currentParent);
    }
    return policy.name;

    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:

    if (isConciergeChatReport(report)) {
    formattedName = CONST.CONCIERGE_DISPLAY_NAME;
    }

    App/src/libs/ReportUtils.ts

    Lines 5925 to 5927 in 7a6393d

    props.transactions,
    props.isReportArchived,
    props.reports,

    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.

    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

    Image
  10. rbur0425 commented on Feb 25, 2026

    @rbur0425

    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:

    1. src/CONST/index.ts — add a constant:
      CHRONOS_DISPLAY_NAME: 'Chronos',

    2. 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;
      }

    3. 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.

  11. melvin-bot commented on Feb 25, 2026

    @melvin-bot

    📣 @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:

    1. Make sure you've read and understood the contributing guidelines.
    2. 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.
    3. 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.
    4. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.
      Screen Shot 2022-11-16 at 4 42 54 PM
      Format:
    Contributor details
    Your Expensify account email: <REPLACE EMAIL HERE>
    Upwork Profile Link: <REPLACE LINK HERE>
    
  12. 39 remaining items

  13. melvin-bot commented on Mar 25, 2026

    @melvin-bot

    Reviewing label has been removed, please complete the "BugZero Checklist".

  14. melvin-bot commented on Mar 25, 2026

    @melvin-bot

    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:

    • @rojiphil requires payment through NewDot Manual Requests
  15. melvin-bot commented on Mar 25, 2026

    @melvin-bot

    @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]

  16. melvin-bot commented on Mar 25, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

  17. rojiphil commented on Mar 31, 2026

    @rojiphil
    Contributor

    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.

    Regression Test Proposal Template

    Regression Test Proposal

    Precondition:

    Test:

    1. Open the app and search for "Chronos" (or any 1:1 DM report whose personal details may load after options are initialized)
    2. Verify the search result displays the correct name (e.g., "Chronos") instead of "Chat Report"
    3. Click on the result and verify the chat header also shows the correct name
    4. Verify that no errors appear in the JS console

    Do we agree 👍 or 👎

    Zapier Logs Run ID: 00040eee-e145-a0ea-aa47-f1122d256854
  18. melvin-bot commented on Apr 1, 2026

    @melvin-bot

    Payment Summary

    Upwork Job

    BugZero Checklist (@mallenexpensify)

    • (if NewFeature) I have created a PR for any necessary HelpDot updates, or I confirmed no updates are necessary.
    • I have verified the correct assignees and roles are listed above and updated the necessary manual offers
    • I have verified that there are no duplicate or incorrect contracts on Upwork for this job (https://www.upwork.com/ab/applicants/2026657268852610505/hired)
    • I have verified the PR was not reverted
    • I have applied any discounts due to bugs/regressions introduced by this PR
    • I have paid out the Upwork contracts or cancelled the ones that are incorrect
    • I have verified the payment summary above is correct
  19. mallenexpensify commented on Apr 2, 2026

    @mallenexpensify
    Contributor

    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)

  20. quinthar commented on Apr 13, 2026

    @quinthar
    Contributor

    Approved $250 to @rojiphil

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

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributor

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions