QueryVBDOperation - java.lang.ArrayIndexOutOfBoundsException

we are observing so many entries like below in Pegarules.log file in production environment.
2019-06-20 07:56:55,174 [n-operation.thread-0] [ STANDARD] [ ] [ ] (ce.operation.QueryVBDOperation) FATAL - []:5751 [vbd] [3.8] null

I am not getting any clue about this error. does it indicating any bad health?

we are using Pega 7.3.1.PFA, complete log file


Keep up to date on this post and subscribe to comments

June 24, 2019 - 2:31am


This is apparently coming from activity called "populatemeasurementmapper" which is then calling "retrievedata" finally generating the error on step5.

Can you check what this step5 is doing exactly, usually this error is due to a function trying to split a string for example which is too small or something like that.

June 24, 2019 - 6:40am
Response to MarcLasserre_GCS

Hi Marc,

This is getting invoked as part of retrieving campaign performance details from IH tables.On step5 of retrievedata, its trying to create the query and call VBD service.

there it was throwing the error.

Please find below code snippet where we could see multiple string manipulations and we could not find the culprit function for the error.

It would be great help if you could help here

Code snippet :

if (null == resultsPg) {
 resultsPg = tools.createPage("Embed-PegaMKT-Measurement-Definition-Interaction", "QueryResultsPage");

// Now switching to com.pega.decision package structure...
//get result
try {
 com.pega.decision.vbd.service.VBDService service = pega_decisionengine_vbd.pzGetVBDService(tools);
 com.pega.decision.vbd.query.QueryResult result = service.query(query);

 //print result
 if (result != null && result.hasValues()) {
  double[] resultArr = result.getValues();
  for (int i=0; i<resultArr.length; i++) {
   //Put the result into the measurement result map, keyed by name.
   double[] theResult = new double[1];
   theResult[0] = resultArr[i];
   measurementResultsMap.put("{" + measurementNameList.get(i) + "}", theResult);
 else if (result.entrySet() != null) {
  //We had grouped results - walk the QueryResult object's entries
  Iterator setIterator = result.entrySet().iterator();
  //for reference - this is the total tally of the requested measurements across all binned results
  double[] runningTally = new double[measurementNameList.size()];
  int binIndex = 0;
  ClipboardPage labelsPage = tools.findPage("D_MKTTimeIntervalLabels");

  while (setIterator.hasNext()) {
   try {
    com.pega.decision.vbd.query.QueryResult.ResultEntry myResult = (com.pega.decision.vbd.query.QueryResult.ResultEntry);
    com.pega.decision.vbd.query.QueryResult myQueryResult = (com.pega.decision.vbd.query.QueryResult)myResult.getValue();
    com.pega.decision.vbd.client.GroupedValue myGroupedValue = (com.pega.decision.vbd.client.GroupedValue)myResult.getKey();
    //assuming a time binning as first grouping - grouped values will be in the format "default=x" where x is the number of bin intervals from start date
    String groupedValueIndex = (String)myGroupedValue.get("default");
    binIndex = Integer.parseInt(groupedValueIndex);    
    //keep track of the lowest bin interval - this will help us match up the proper label for displaying the results
    binOffset = binIndex + 1;

    String intervalLabel = "";
    String binLabel = "";
    ClipboardProperty labelsProp = null;
    if (labelsPage != null) {
     labelsProp = labelsPage.getProperty("TimeIntervalLabels");
    if (null != labelsProp) {
     intervalLabel = labelsProp.getStringValue(binOffset);
     binLabel = intervalLabel;
     intervalLabel = intervalLabel.replaceAll(" ", "_").replaceAll("-", "");
    if (intervalLabel.length() <= 0) {
     intervalLabel = "All";
     binLabel = intervalLabel;
    //Year will be numeric - append a character to allow for use as PageGroup index
    else if ("Year".equals(intervalParam)) {
     intervalLabel = "Y" + intervalLabel;
    //our results were only binned by time in this case - update runningTally and store the results indexed by the bin interval
    if (myQueryResult.hasValues()) {
     double[] myDouble = myQueryResult.getValues(myGroupedValue);
     for (int i = 0; i < myDouble.length; i++) {
      runningTally[i] = runningTally[i] + myDouble[i];

      ClipboardPage r1 = resultsPg.getPage("ResultsGroup(" + intervalLabel + ")");
      r1.putString("GlobalGroupingLabel", binLabel);
      ClipboardPage r2 = r1.getPage("ResultsGroup(" + measurementNameList.get(i) + ")");
      ClipboardProperty measure = r2.getProperty("Measure1");
      ClipboardProperty ordering = r2.getProperty("SortIndex");
     //store the bin results indexed by bin interval, for further calculations
    } else if (myQueryResult.entrySet() != null) {
        // We have time & local grouping
     Iterator setIteratorInner = myQueryResult.entrySet().iterator();
     //for reference - this is the total tally of the requested measurements across all binned results
     double[] innerTally = new double[measurementNameList.size()];

     while (setIteratorInner.hasNext()) {
      try {
       com.pega.decision.vbd.query.QueryResult.ResultEntry innerResult = (com.pega.decision.vbd.query.QueryResult.ResultEntry);
       com.pega.decision.vbd.query.QueryResult innerQueryResult = (com.pega.decision.vbd.query.QueryResult)innerResult.getValue();
       com.pega.decision.vbd.client.GroupedValue innerGroupedValue = (com.pega.decision.vbd.client.GroupedValue)innerResult.getKey();
       //assuming a string-based binning as our inner/local binning - inner grouped results will be in format "levelParam=xyz"
       String groupedValueIndexInner = (String)innerGroupedValue.get(levelParam);
       //remove <> symbols; translate spaces to _ character for clarity
       groupedValueIndexInner = groupedValueIndexInner.replaceAll("<", "").replaceAll(">", "").replaceAll(" ", "_").replaceAll("-", "");

       //our results were only binned by time in this case - update runningTally and store the results indexed by the bin interval
       if (innerQueryResult.hasValues()) {
        double[] innerDouble = innerQueryResult.getValues(innerGroupedValue);
        ClipboardPage r1 = resultsPg.getPage("ResultsGroup(" + intervalLabel +")");
        r1.putString("GlobalGroupingLabel", binLabel);
        ClipboardPage r2 = r1.getPage("ResultsGroup(" + groupedValueIndexInner + ")");
        r2.putString("LocalGroupingLabel", (String)innerGroupedValue.get(levelParam));
        r2.putString("GlobalGroupingLabel", binLabel);

        for (int i = 0; i < innerDouble.length; i++) {
         innerTally[i] = innerTally[i] + innerDouble[i];
         ClipboardPage r3 = r2.getPage("ResultsGroup(" + measurementNameList.get(i) + ")");
         ClipboardProperty innerMeasure = r3.getProperty("Measure1");
         ClipboardProperty ordering = r3.getProperty("SortIndex");
      catch (Throwable t) {
       oLog.error("Not able to get the timeframe and locally grouped value from VBD");
       oLog.error("Error is " + t.toString());
    } else {"myQueryResult has  NO values" );
   } catch (Throwable t){
    oLog.error("Not able to get the timeframe grouped value from VBD");
    oLog.error("Error is " + t.toString());

  } //while
catch (Exception e) { oLog.error("Unable to query VBD: " + e.getMessage()); }

//This activity will recursively call itself to arrive at the calculated set of answers for the requested KPI (Operand)
paramPage.putObject("Expression", paramName);
StringMap keys = new HashStringMap();
keys.putString("pyActivityName", "CalculateKPIExpression");
tools.doActivity(keys, resultsPg, paramPage);

June 24, 2019 - 9:25am
Response to PonnurangamN2827

Also, we are observing multiple entries like below in production

Unable to query VBD: nul

during multichannel campaign run today .

but if i change actual start date, i will be losing all IH data? i dont think this is correct solution in our case.

Please suggest here