Skip to main content

Feed

Treten Sie mit anderen Trailblazers in Verbindung. Stellen und beantworten Sie Fragen, um Ihre Fertigkeiten und Ihr Netzwerk auszubauen.

Environment: Full Copy Sandbox  Data Cloud was [enabled directly in the sandbox / inherited from Production]. Salesforce release: [Winter ‘27 / other]. 

 

Use case: Enable Agentforce Data Library and point it to internal CRM Knowledge Base articles. 

 

Steps taken: 

 

Enabled Data Cloud and assigned the Data Cloud Architect permission set to the System Admin user. 

Installed the latest Service Cloud bundle in the CRM Connector. 

Activated the Home Org CRM Connector. 

Created an Agentforce Data Library pointing to Knowledge Articles. 

 

The library status shows every step as successful: ingesting data into Data Cloud, creating data lake objects, mapping DLOs to DMOs, creating the search index, and building a retriever from the search index. 

 

Problem 1: Data Explorer queries fail 

 

DLO Knowledge_kav_Home fails with: “Something’s not right with the query. Check the columns or filter and try again.” TraceIds: 220ae71e7e7e017b, 6e0ef3579db8d062. 

DMO KA_CompanyName_KB_Data_Libr_index__dlm fails with the same error. TraceId: eb5ed4f4e67ee6d1. 

DMO KA_CompanyName_KB_Data_Libr_chunk__dlm fails with the same error. TraceId: b0b718d9efff328a. 

Other DMOs fail too, each with a different TraceId. 

Data Explorer lists the object’s metadata (46 columns for Knowledge_kav_Home, data space default), but running the query returns the error. 

 

Problem 2: Search Index Advanced Setup fails 

After creating the Data Library, I tried to create/update a search index using Advanced Setup. I selected the DMO ssot__KnowledgeArticleVersion__dlm and clicked Next. On the “Select Fields to Chunk” screen I get: “We hit a snag. Something went wrong while retrieving attachments.” 

 

What I’ve checked so far: 

 

Data stream status / records processed: [result] 

Minimal query (only Id column) in Data Explorer: [works / fails] 

Same query in Query Editor: [works / fails, error text] 

Other, non-Knowledge objects in Data Explorer: [work / fail] 

Incognito / different browser: [result] 

Retriever test in Prompt Builder or Agent Builder: [returns results / returns nothing] 

User permission sets: [list] 

Published Knowledge articles in the sandbox: [count] 

 

Questions: 

 

Is there a known limitation or extra provisioning step for Data Cloud and Agentforce Data Libraries in a Full Copy Sandbox? 

Has anyone seen Data Explorer return this generic “Something’s not right with the query” error on DLOs/DMOs created by a Data Library, even though ingestion shows success? 

Is a backend job (indexing, ingestion, or DMO mapping) still running or stuck after creation? How can I confirm this from the UI? 

Could the “Something went wrong while retrieving attachments” error in Advanced Setup come from a permission, a data space, or a Knowledge setting? What should I check? 

Do I need any extra permission set beyond Data Cloud Architect for the admin user to query these objects? 

Should I open a Salesforce Support case with these TraceIds, or is there a fix I should try first?

0/9000

Hi Salesforce Community,

I have created an Apex class named SingleEmailLimitController to check the daily single-email limit in my Salesforce organization. The class retrieves the email limit using System.OrgLimits.getMap() and returns the daily limit, emails used, emails remaining, and a status message.

I am trying to write an Apex test class to achieve 100% code coverage, but I am facing difficulties covering all the conditional branches and the exception-handling block.

My main challenges are:

  1. Testing the scenario where limits.get('SingleEmail') returns null.
  2. Covering the condition where the daily email limit has been reached or exceeded.
  3. Covering the condition where 10 or fewer emails remain.
  4. Covering the condition where sufficient email capacity remains.
  5. Covering the catch (Exception e) block.
  6. Testing these scenarios without depending on the actual email usage and limits of the Salesforce organization.

Since System.OrgLimits.getMap() returns system-provided limit information, I am unsure how to simulate these different scenarios in an Apex test.

My Apex controller:

public with sharing class SingleEmailLimitController {

public class EmailLimitResponse {

@InvocableVariable(label='Daily Single Email Limit')

public Integer dailyLimit;

@InvocableVariable(label='Emails Used')

public Integer emailsUsed;

@InvocableVariable(label='Emails Remaining')

public Integer emailsRemaining;

@InvocableVariable(label='Limit Status Message')

public String statusMessage;

}

@InvocableMethod(

label='Check Single Email Limit'

description='Checks daily email usage and returns a status message.'

)

public static List<EmailLimitResponse> checkSingleEmailLimit(

List<String> requests

) {

EmailLimitResponse result = new EmailLimitResponse();

List<EmailLimitResponse> results =

new List<EmailLimitResponse>();

try {

Map<String, System.OrgLimit> limits =

System.OrgLimits.getMap();

System.OrgLimit emailLimit = limits.get('SingleEmail');

if (emailLimit == null) {

result.statusMessage =

'Unable to retrieve the daily email limit.';

} else {

result.dailyLimit = emailLimit.getLimit();

result.emailsUsed = emailLimit.getValue();

result.emailsRemaining =

Math.max(

0,

result.dailyLimit - result.emailsUsed

);

if (result.emailsUsed >= result.dailyLimit) {

result.statusMessage =

'Daily email limit exceeded. No email capacity remains.';

} else if (result.emailsRemaining <= 10) {

result.statusMessage =

'Daily email limit almost reached. Only ' +

result.emailsRemaining + ' emails remaining.';

} else {

result.statusMessage =

'Email capacity available. ' +

result.emailsRemaining +

' emails remaining out of ' +

result.dailyLimit + '.';

}

}

} catch (Exception e) {

result.statusMessage =

'Unable to check email limit: ' + e.getMessage();

}

results.add(result);

return results;

}

}

My questions:

  • Is it possible to achieve 100% code coverage for this controller without changing its implementation?
  • If not, what is the recommended approach for making the limit values testable?
  • How can I write a complete Apex test class that covers all the conditional branches and the exception-handling block?
  • Would using a @TestVisible helper method or an injectable service be a suitable solution?

Please share a working example of the controller changes, if necessary, and the corresponding Apex test class.

Thank you for your help! 

 

#Salesforce Developer  #Salesforce Admin  #Trailhead Challenges  #Trailhead

1 Antwort
  1. 16. Okt., 15:07

    @HARIPRASAD Km I don't believe there is a way to achieve 100% without changing the class... first - emailLimit will never be null, so you will not get into that block. There is also no way to set org limits from a test, so the 'close to limit' and 'at limit' branches are not going to hit. I also don't see anyway you would end up in the catch block - nothing in here would fail.

     

    There are some things you can do to refactor that could help, but you'd essentially just be making the changes to get higher coverage, when you could easily get the 75% keeping the class as is. Regardless, if that is your goal, I'll try to help:

     

     The problem is this line:

    Map<String, System.OrgLimit> limits = System.OrgLimits.getMap(); 

     

    The class fetches those numbers itself, so a test can’t get in between. Flip it around - define a small interface with getDailyLimit() and getEmailsUsed(), put the System.OrgLimits call in one class that implements it, and hold that in a @TestVisible private static field on the controller. Production uses the real one by default, and your test reassigns the field to a mock. Your if/else logic doesn’t change at all. 

     

    From there 5000/4995 hits “almost reached”, 5000/5000 hits exceeded, 5000/100 hits the normal path, nulls hit “unable to retrieve”, and a mock whose getter throws hits the catch. Keep one test that doesn’t swap the provider so the real one gets covered too.

     

     

    Here are the classes: 

    public with sharing class SingleEmailLimitController {

    public class EmailLimitResponse {

    @InvocableVariable(label='Daily Single Email Limit')

    public Integer dailyLimit;

    @InvocableVariable(label='Emails Used')

    public Integer emailsUsed;

    @InvocableVariable(label='Emails Remaining')

    public Integer emailsRemaining;

    @InvocableVariable(label='Limit Status Message')

    public String statusMessage;

    }

    public interface LimitProvider {

    Integer getDailyLimit();

    Integer getEmailsUsed();

    }

    public class OrgLimitProvider implements LimitProvider {

    public Integer getDailyLimit() {

    System.OrgLimit l = System.OrgLimits.getMap().get('SingleEmail');

    return l == null ? null : l.getLimit();

    }

    public Integer getEmailsUsed() {

    System.OrgLimit l = System.OrgLimits.getMap().get('SingleEmail');

    return l == null ? null : l.getValue();

    }

    }

    @TestVisible

    private static LimitProvider provider = new OrgLimitProvider();

    @InvocableMethod(

    label='Check Single Email Limit'

    description='Checks daily email usage and returns a status message.'

    )

    public static List<EmailLimitResponse> checkSingleEmailLimit(List<String> requests) {

    List<EmailLimitResponse> results = new List<EmailLimitResponse>();

    if (requests == null || requests.isEmpty()) {

    return results;

    }

    EmailLimitResponse evaluated = evaluate();

    for (Integer i = 0; i < requests.size(); i++) {

    EmailLimitResponse r = new EmailLimitResponse();

    r.dailyLimit = evaluated.dailyLimit;

    r.emailsUsed = evaluated.emailsUsed;

    r.emailsRemaining = evaluated.emailsRemaining;

    r.statusMessage = evaluated.statusMessage;

    results.add(r);

    }

    return results;

    }

    @TestVisible

    private static EmailLimitResponse evaluate() {

    EmailLimitResponse result = new EmailLimitResponse();

    try {

    Integer dailyLimit = provider.getDailyLimit();

    Integer emailsUsed = provider.getEmailsUsed();

    if (dailyLimit == null || emailsUsed == null) {

    result.statusMessage = 'Unable to retrieve the daily email limit.';

    } else {

    result.dailyLimit = dailyLimit;

    result.emailsUsed = emailsUsed;

    result.emailsRemaining = Math.max(0, dailyLimit - emailsUsed);

    if (emailsUsed >= dailyLimit) {

    result.statusMessage =

    'Daily email limit exceeded. No email capacity remains.';

    } else if (result.emailsRemaining <= 10) {

    result.statusMessage =

    'Daily email limit almost reached. Only ' +

    result.emailsRemaining + ' emails remaining.';

    } else {

    result.statusMessage =

    'Email capacity available. ' + result.emailsRemaining +

    ' emails remaining out of ' + dailyLimit + '.';

    }

    }

    } catch (Exception e) {

    result.statusMessage = 'Unable to check email limit: ' + e.getMessage();

    }

    return result;

    }

    }

     

     

    And Test Class

    @IsTest

    private class SingleEmailLimitControllerTest {

    private class MockException extends Exception {}

    private class MockProvider implements SingleEmailLimitController.LimitProvider {

    private Integer dailyLimit;

    private Integer emailsUsed;

    private MockProvider(Integer dailyLimit, Integer emailsUsed) {

    this.dailyLimit = dailyLimit;

    this.emailsUsed = emailsUsed;

    }

    public Integer getDailyLimit() { return dailyLimit; }

    public Integer getEmailsUsed() { return emailsUsed; }

    }

    private class ThrowingProvider implements SingleEmailLimitController.LimitProvider {

    public Integer getDailyLimit() { throw new MockException('simulated failure'); }

    public Integer getEmailsUsed() { return null; }

    }

    private static List<SingleEmailLimitController.EmailLimitResponse> run() {

    return SingleEmailLimitController.checkSingleEmailLimit(new List<String>{ 'go' });

    }

    @IsTest

    static void limitUnavailableReturnsMessage() {

    SingleEmailLimitController.provider = new MockProvider(null, null);

    Test.startTest();

    List<SingleEmailLimitController.EmailLimitResponse> results = run();

    Test.stopTest();

    Assert.areEqual(

    'Unable to retrieve the daily email limit.',

    results[0].statusMessage

    );

    Assert.isNull(results[0].dailyLimit);

    }

    @IsTest

    static void limitExceededReturnsMessage() {

    SingleEmailLimitController.provider = new MockProvider(5000, 5000);

    Test.startTest();

    List<SingleEmailLimitController.EmailLimitResponse> results = run();

    Test.stopTest();

    Assert.areEqual(0, results[0].emailsRemaining);

    Assert.isTrue(results[0].statusMessage.contains('limit exceeded'));

    }

    @IsTest

    static void almostReachedReturnsMessage() {

    SingleEmailLimitController.provider = new MockProvider(5000, 4995);

    Test.startTest();

    List<SingleEmailLimitController.EmailLimitResponse> results = run();

    Test.stopTest();

    Assert.areEqual(5, results[0].emailsRemaining);

    Assert.isTrue(results[0].statusMessage.contains('almost reached'));

    }

    @IsTest

    static void capacityAvailableReturnsMessage() {

    SingleEmailLimitController.provider = new MockProvider(5000, 100);

    Test.startTest();

    List<SingleEmailLimitController.EmailLimitResponse> results = run();

    Test.stopTest();

    Assert.areEqual(4900, results[0].emailsRemaining);

    Assert.isTrue(results[0].statusMessage.contains('Email capacity available'));

    }

    @IsTest

    static void exceptionIsCaught() {

    SingleEmailLimitController.provider = new ThrowingProvider();

    Test.startTest();

    List<SingleEmailLimitController.EmailLimitResponse> results = run();

    Test.stopTest();

    Assert.isTrue(results[0].statusMessage.startsWith('Unable to check email limit:'));

    }

    @IsTest

    static void outputSizeMatchesInputSize() {

    SingleEmailLimitController.provider = new MockProvider(5000, 100);

    Test.startTest();

    List<SingleEmailLimitController.EmailLimitResponse> results =

    SingleEmailLimitController.checkSingleEmailLimit(

    new List<String>{ 'a', 'b', 'c' }

    );

    Test.stopTest();

    Assert.areEqual(3, results.size());

    Assert.areEqual(4900, results[2].emailsRemaining);

    }

    @IsTest

    static void emptyInputReturnsEmptyList() {

    Test.startTest();

    List<SingleEmailLimitController.EmailLimitResponse> results =

    SingleEmailLimitController.checkSingleEmailLimit(new List<String>());

    Test.stopTest();

    Assert.areEqual(0, results.size());

    }

    @IsTest

    static void realProviderReturnsAResult() {

    Test.startTest();

    List<SingleEmailLimitController.EmailLimitResponse> results = run();

    Test.stopTest();

    Assert.areEqual(1, results.size());

    Assert.isNotNull(results[0].statusMessage);

    }

    }

     

     

    Let me know if this all makes sense. Happy to talk through it more

0/9000

What is the best place to begin with a salesforce career? What certificate??

#Trailhead
0/9000

I'm currently working on the "Create Apex Agent Job" challenge as part of the "Agent customization via Apex" 

badge. 

 

Despite having completed all the required steps in my designated org (in two new different orgs requested), I keep running into a verification error. 

 

Here's what I've already checked:

 

  • I'm verifying the challenge against the correct org username: apexlegendbadge@sfdc.comand for the other org : test2@legend.apex
  • I've successfully created and configured both the Apex class and the custom action as instructed
  • The "Einstein Copilot" agent is set up and currently in Active status
  • I've tried clearing my browser cache and logging out and back in — the error still persists
  • I've tried in another browser and I have tried in an incognito window... error still here

 

Has anyone run into this recently? Any suggestions or workarounds would be greatly appreciated. Thanks in advance! 

 

#Trailhead Challenges  #Trailhead

6 Antworten
0/9000

Our agents normally receive e-mail notifications when a lead is assigned to them. But as of this week, they are no longer getting them, even when ticking the 'send email notification' box when assigning the lead. 

 

#Salesforce Developer

1 Antwort
  1. Eric Burté (DEVOTEAM) Forum Ambassador
    16. Okt., 22:10

    Hello @Maria Mittleman

    are they coming from an API Call or manually created/assigned? 

    Please have a look at this help article on "Assignment rules do not send notification emails for Leads or Cases created via API" :

    https://help.salesforce.com/s/articleView?id=000384839&type=1

     

    Eric

0/9000

#Trailhead Challenges #Salesforce

 

What practical exercises and real-time business scenarios should a Salesforce learner focus on to master Apex classes, triggers, collections, exception handling, governor limits, and test classes while following Salesforce best practices?

1 Antwort
  1. Eric Burté (DEVOTEAM) Forum Ambassador
    16. Okt., 22:07

    Hello @Sai Pavani Yamsani, try https://www.apexsandbox.io/

    to test your Apex. 

    Look for specific related modules and Salesforce documentation for the other topics 

    Eric

0/9000

#Salesforce Developer #Developer Relation

 

What real-world Salesforce projects should a fresher build in a Developer Org to demonstrate practical knowledge of objects, relationships, flows, validation rules, reports, dashboards, and security in technical interviews?

1 Antwort
  1. Eric Burté (DEVOTEAM) Forum Ambassador
    16. Okt., 22:06
0/9000

#Trailhead #Salesforce Admin #Salesforce DeveloperFor a learner who has completed several Trailhead modules and earned multiple badges, what is the best step-by-step roadmap to strengthen Salesforce Admin and Developer skills and become job-ready?

1 Antwort
  1. Eric Burté (DEVOTEAM) Forum Ambassador
    16. Okt., 22:04

    Hello @Sai Pavani Yamsani

    , practice, practice, practice. Do not hesitate to apply what you have learned in modules. Follow both certification exam guides for the content to deep dive and train on a playground / personal dev edition to try what you have learned. 

    Eric

0/9000

Dear Community! 

 

The Trailhead community will be shifted to slack in a few weeks. Is there any means of testing the access before the great day?  

 

If so, where and how? 

 

cheers  

 

#Trailhead

1 Antwort
  1. Eric Burté (DEVOTEAM) Forum Ambassador
    16. Okt., 21:52

    Hello @f ja there is a limited scope beta testing in progress but that is already closed

    • October 30, 2026: Online Trailblazer Community website transitions to read-only.
    • November 2026: General Availability launch of the Trailblazer Community in Slack.

    Please review the FAQ

    for more information 

    Eric

0/9000

#Salesforce #Salesforce Admin #Salesforce DeveloperWhat is the recommended approach for deploying Salesforce customizations between development, testing, and production environments using sandboxes, change sets, Salesforce CLI, and DevOps Center while maintaining sufficient test coverage and minimizing deployment failures?

1 Antwort
  1. 16. Okt., 21:49

    The three tools solve the same problem (moving metadata between orgs) at different levels of maturity, so the practical answer is to pick based on team skills and how much control you need. 

    1. Change sets (declarative, org-to-org) 

    • You select components one at a time in the source org, upload to a connected org, then validate and deploy in the target.
    • It’s fine for a one-off tweak or an admin-only team.
    • Change sets don’t work with the Salesforce CLI or source-driven development in general, so nothing lands in version control. Salesforce isn’t planning further enhancements to them, and DevOps Center is positioned to replace them. 
    • Common pain points: you rebuild the component list for every hop, there’s no easy rollback, and large change sets are hard to troubleshoot.

    2. Salesforce CLI (code-first, source-driven)

    • Keep metadata in Git as the source of truth. Develop in scratch orgs or sandboxes, and use sf project retrieve start and sf project deploy start to move changes.
    • Validate before deploying (--dry-run) and run specified tests (--test-level RunSpecifiedTests) so deployments stay fast and safe.
    • Wire it into CI/CD (GitHub Actions, GitLab CI, Jenkins, Azure DevOps): run tests on pull requests, deploy to the integration sandbox on merge, then promote to UAT and production.
    • Use delta deployments (for example the sfdx-git-delta plugin) to deploy only what changed, and use sf org login jwt with a connected app for non-interactive authentication.
    • This gives the most control and the best auditability, but it requires developers who are comfortable with Git and the command line.

    3. DevOps Center (declarative UI on top of Git)

    • It’s a free Salesforce tool that gives a point-and-click pipeline. It’s built on the same foundation as the Salesforce CLI, and each project is tied to a GitHub repository.   Refer this: devops-center-for-hybrid-teams
    • Work items are the main object for defining and tracking changes through their lifecycle. A work item is promoted from one stage to the next in the pipeline, for example Development, QA, UAT, and Production. 
    • Instead of rebuilding a component list per hop, you create the list once and the work item carries it through the pipeline. 
    • Combining work items merges their feature branches into one branch, which helps with conflicts and dependencies. Because it sits on GitHub, you can also use native GitHub capabilities such as GitHub Actions. 
    • It works for hybrid teams: admins stay in the UI while developers keep using VS Code, the CLI, and pull requests. Deployments can be done from DevOps Center or externally with the CLI plugin’s sf project deploy pipeline command, which was in beta when that was written, so check its current status. 

    Which one should I use?

    • Admin-only team, small and infrequent changes → Change Sets (or move to DevOps Center)
    • Mixed admin and developer team, wants Git without everyone learning the CLI → DevOps Center
    • Developer-led team needing CI/CD, test gating, scratch orgs, unlocked or managed packages → Salesforce CLI + CI/CD
    • Large or regulated enterprise needing approvals, rollback and audit → CLI-based CI/CD, or a commercial DevOps tool.
0/9000