---
title: "BatchQueueEntry Object"
id: "batchqueueentry-object"
project: "MES User Manual"
url: "https://docs.sepasoft.com/articles/user-manual/batchqueueentry-object"
updated: 2026-07-31T14:56:45Z
---

# BatchQueueEntry Object

**Sepasoft MES Module Suite**
   
## BatchQueueEntry Object

###  Overview 
 
A Batch Queue Entry represents one batch scheduled for or undergoing execution on a Process Cell. Each entry binds a unique Batch ID to a runtime Batch Control Recipe, optional Batch Formula, unit assignments, scale/quantity overrides, and scheduling metadata. Queue entries live in the gateway batch execution manager — they are not persisted as standalone MES objects and cannot be saved with system.mes.saveMESObject().

Create entries with system.mes.batch.queue.addEntry(), update idle entries with addOrUpdateEntry(), and drive execution with batch-level commands (executeEntryCommand()) and step-level APIs that accept either a batch ID or a BatchQueueEntry reference. When a batch completes and is reset or removed, the entry leaves the active queue; historical batch IDs remain reserved and cannot be reused.
 
###  Obtaining a BatchQueueEntry 
 
```python
# Create a new queue entry from a master recipe or formula link
recipeLink = system.mes.batch.recipe.getRecipeLink('Standard Mix', None)
entry = system.mes.batch.queue.addEntry(
    masterRecipeOrFormulaLink=recipeLink,
    batchName='Mix Run 42',
    batchID='BATCH-042',
    priority=1,
    scale=1.0,
    quantity=500.0,
    unitAssignments={'Mix': 'Enterprise\\Site\\Area\\Process Cell\\Mixer 1'},
    batchParameters={'Target pH': 7.2},
    processCellPath='Enterprise\\Site\\Area\\Process Cell'
)

# Load an existing entry by batch ID
entry = system.mes.batch.queue.getEntry('BATCH-042')

# List entries (use paging when the queue is large)
entries = system.mes.batch.queue.getEntries(0, 100, 'BATCH-*')
```


### Object Identity 

| Field | Value |
| --- | --- |
| Type name | BatchQueueEntry |
| Kind | Runtime response object (not an AbstractMESObject) |
| Required module | Batch (Production) |
| Persistence | In-memory queue on the gateway that owns the process cell; control recipe data is stored as MES objects |
| Primary key | Batch ID (getBatchID()) — globally unique across current and previously executed batches |

##  Related Objects 

| Relationship | Type | Notes |
| --- | --- | --- |
| Control recipe | BatchControlRecipe | Created when the batch is queued; accessed via getRecipeControlLink(), getRecipeLink(), or getControlRecipeLink() |
| Master recipe | BatchMasterRecipe | Source template; UUID available from getMasterRecipeUUID() after queuing |
| Formula | BatchFormula | Optional; link from getBatchFormulaLink() when the batch was created from or linked to a formula |
| Process cell | MESProcessCell | Execution location; link from getProcessCellLink(), path from getProcessCellEquipmentPath() |
| Assigned units | MESObjectLink or equipment path | Per unit procedure name in getAssignedUnitMap() |

There is no parent/child MES object hierarchy. Unit procedure names in the assigned-unit map must match friendly names in the control recipe.
 
###  Properties 
 
All properties are accessed through getter methods on the BatchQueueEntry instance returned by addEntry(), getEntry(), getEntries(), or changeEntryPriority(). Most fields are read-only after the control recipe is created; see Exceptions and Constraints for what can change.
 
####  Identification and recipe references 

| Property | Access | Type | Description |
| --- | --- | --- | --- |
| Batch Name | getBatchName() | String | Display name for the batch. Multiple queue entries may share the same batch name. Defaults to the master recipe name when omitted at addEntry(). |
| Batch ID | getBatchID() | String | Unique identifier. Required at creation; cannot be blank or reused. |
| Recipe Name | getRecipeName() | String | Friendly name of the control recipe instance. |
| Parent Recipe Name | getParentRecipeName() | String | Name of the Batch Master Recipe Class folder containing the source master recipe, when available. |
| Master Recipe UUID | getMasterRecipeUUID() | String | UUID of the source Batch Master Recipe. |
| Recipe Control Link | getRecipeControlLink() | MESObjectLink | Link to the runtime Batch Control Recipe. Synonyms: getControlRecipeLink(), getRecipeLink(). |
| Recipe User Version | getRecipeUserVersion() | Integer | User version copied from the master recipe at queue time. |
| Batch Formula Link | getBatchFormulaLink() | MESObjectLink | Link to the Batch Formula when one is associated. Use hasBatchFormulaLink() to test. |

####  Sizing and priority 

| Property | Access | Type | Description |
| --- | --- | --- | --- |
| Scale | getScale() / setScale(scale) | Double | Scale factor applied to the control recipe. Used in recipe calculations and by the allocation manager. |
| Quantity | getQuantity() / setQuantity(quantity) | Double | Batch size. Use hasQuantity() to test for a positive quantity. |
| Units | getUnits() | String | Unit of measure for quantity, when specified at creation. |
| Priority | getPriority() | Integer | Scheduling priority where 1 is highest. Clamped to a minimum of 1 at construction. Change while idle via changeEntryPriority() or addOrUpdateEntry(). |

####  Process cell and queue behavior 

| Property | Access | Type | Description |
| --- | --- | --- | --- |
| Process Cell Link | getProcessCellLink() / setProcessCellLink(link) | MESObjectLink | Process cell that owns execution. Required at creation. Updating the link also refreshes the equipment path. |
| Process Cell Equipment Path | getProcessCellEquipmentPath() | String | Equipment path of the process cell (for example, Enterprise\\Site\\Area\\Process Cell). |
| Execution Interval | getExecutionInterval() | Long | Polling interval inherited from the process cell configuration. |
| Remove Held From Queue | isRemoveHeldFromQueue() | Boolean | When True, held batches are automatically removed from the queue per process cell settings. |
| Remove Complete From Queue | isRemoveCompleteFromQueue() | Boolean | When True, completed batches are automatically removed from the queue per process cell settings. |
| Remote Queue Entry | isRemoteQueueEntry() | Boolean | True when the entry is owned by a remote gateway in an enterprise deployment. |

####  Execution state and scheduling 

| Property | Access | Type | Description |
| --- | --- | --- | --- |
| Batch State | getBatchState() / setBatchState(state) | String | Cached batch-level execution state (for example, Idle, Running, Held, Complete). Prefer system.mes.batch.queue.getStatus(entry) for the authoritative live state during execution. |
| Blocked Reason | getBlockedReason() / setBlockedReason(reason) | String | Reason the batch is blocked from starting or continuing, when set by the execution engine. |
| Last Activity Date Time | getLastActivityDateTime() | LocalDateTime | Timestamp of the last queue activity. |
| Scheduled Begin / End | getScheduledBeginDateTime() / getScheduledEndDateTime() | LocalDateTime | Planned schedule window, when populated by scheduling integrations. |
| Actual Begin / End | getActualBeginDateTime() / getActualEndDateTime() | LocalDateTime | Actual execution window, when recorded. |
| Original Begin / End | getOriginalBeginDateTime() / getOriginalEndDateTime() | LocalDateTime | Original schedule before rescheduling, when recorded. |

###  Unit assignments 

| Property | Access | Type | Description |
| --- | --- | --- | --- |
| Assigned Unit Map | getAssignedUnitMap() | Map | Read-only map of unit procedure name → equipment path or MESObjectLink. |
| Unit (by name) | getUnit(unitProcedureName) / setUnit(name, linkOrPath) | Serializable | Get or set one unit assignment. Values may be an equipment path String or MESObjectLink. |

###  BatchQueueEntry Methods 

| Method | Return type | Description |
| --- | --- | --- |
| getRecipe() | BatchControlRecipe | Loads the control recipe object. Synonym: getControlRecipe(). |
| withNewPriority(priority) | BatchQueueEntry | Returns a copy with a new priority and the same unit assignments. Used internally by changeEntryPriority(). |
| toString() | String | Debug summary: batch name, batch ID, priority, scale, quantity, units, batch state. |

####  Deprecated parameter helpers 
 
These methods write directly to Batch Control Logic and remain for backward compatibility. Prefer system.mes.batch.queue.setParameterValue() and getParameterValueAsString() with full item paths.

| Method | Return type | Description |
| --- | --- | --- |
| setBatchParameter(paramName, value) | None | Deprecated. Sets a procedure-level parameter on the control recipe logic and saves. |
| getBatchParameter(paramName) | Serializable | Deprecated. Returns a procedure-level parameter value as a string. |
| getBatchParameterMap() | Map | Deprecated. Returns visible recipe parameters as a name/value map. |

###  Scope / Availability 

| Context | How to access |
| --- | --- |
| Gateway scripts | system.mes.batch.queue.\* returns and accepts BatchQueueEntry instances |
| Client / Designer / Perspective scripts | Same module via RPC (BatchClientQueueScript → gateway) |
| Perspective UI | Batch List, Batch Controller, and Batch Recipe Monitor components operate on queue entries selected by Batch ID |

Commands that require electronic signature authorization cannot be driven purely from a BatchQueueEntry handle in script — use the Batch List or Batch Controller components for those commands.
 
###  Exceptions and Constraints 

| Situation | Behavior |
| --- | --- |
| Blank batch ID at addEntry() | Exception: "The batch id cannot be blank." |
| Duplicate batch ID in queue | Exception: "The batch id (...) is already in the queue." |
| Reused batch ID from a prior run | Exception: "The batch id (...) has already been used." |
| No process cell at creation | IllegalStateException: "Process cell was not specified and one could not be determined..." |
| removeEntry() while not idle | Exception: "Unable to remove batch queue entry because the batch is not in idle." |
| changeEntryPriority() while active | Exception: "Unable to change priority because batch queue entry is active." |
| addOrUpdateEntry() while not idle (remote) | Exception: "Unable to edit batch queue entry because it is not idle." |
| addOrUpdateEntry() on existing entry | Only priority and unit assignments can change. When the batch is active, only unit assignments can change. |
| executeEntryCommand(COMMAND\_START) on running batch | Exception: "Unable to begin batch queue entry because it is already running." |
| Start from invalid state | Exception: "Unable to begin batch queue entry because it is not in the correct state." |
| Batch ID not in queue | BatchQueueEntryNotFoundException from getEntry() and related APIs |
| Signature-protected commands from script | IllegalAccessException — use operator UI instead |
| Remote process cell on wrong gateway | IllegalAccessException — command must run on the owning gateway |

Use system.mes.batch.queue.getStatus(entry) for live execution state names (Idle, Running, Held, Paused, Complete, and transient -ing states). See ISA-88 state transition matrix for allowed command transitions.
 
### Example Usage

Minimal example — create, inspect, and remove

```python
recipeLink = system.mes.batch.recipe.getRecipeLink('Standard Mix', None)

entry = system.mes.batch.queue.addEntry(
    masterRecipeOrFormulaLink=recipeLink,
    batchID='BATCH-DEMO-001',
    batchName='Demo Mix',
    priority=1,
    scale=1.0,
    quantity=100.0
)

print('Batch ID:', entry.getBatchID())
print('Process cell:', entry.getProcessCellEquipmentPath())
print('Status:', system.mes.batch.queue.getStatus(entry))

# Remove only while idle
if system.mes.batch.queue.getStatus(entry) == 'Idle':
    system.mes.batch.queue.removeEntry(entry)
```


**Complex example 1** — ERP release with unit assignment, parameters, and monitored start
 
Schedule a batch from an external order line: queue the entry with overrides, verify assignments, start the batch, and wait until execution reaches Running before writing a tag or ERP status.
 
```python
import time

# --- Inputs from ERP / tag read ---
orderBatchID = 'ORD-2026-0042'
recipeName = 'Standard Mix'
processCellPath = 'Enterprise\\North Site\\Production\\Reactor Cell'
mixerPath = 'Enterprise\\North Site\\Production\\Reactor Cell\\Reactor 1'
targetQuantity = 750.0
targetScale = 1.0

recipeLink = system.mes.batch.recipe.getRecipeLink(recipeName, None)
if recipeLink is None:
    raise Exception('Master recipe not found: %s' % recipeName)

# Queue with unit and parameter overrides
entry = system.mes.batch.queue.addEntry(
    masterRecipeOrFormulaLink=recipeLink,
    batchName='Order %s' % orderBatchID,
    batchID=orderBatchID,
    priority=2,
    scale=targetScale,
    quantity=targetQuantity,
    processCellPath=processCellPath,
    unitAssignments={'Reactor': mixerPath},
    batchParameters={
        'Order Number': orderBatchID,
        'Target Weight': targetQuantity
    }
)

# Confirm queue metadata before start
logger = system.util.getLogger('erp.batchRelease')
logger.info(
    'Queued %s on %s (priority=%s, scale=%s, qty=%s)' % (
        entry.getBatchID(),
        entry.getProcessCellEquipmentPath(),
        entry.getPriority(),
        entry.getScale(),
        entry.getQuantity()
    )
)

assigned = entry.getAssignedUnitMap()
if assigned.get('Reactor') != mixerPath:
    # Fallback: assign at runtime if the map stores links instead of paths
    system.mes.batch.queue.assignUnit(
        entry,
        '/{}/Reactor',
        mixerPath
    )

# Start and wait for Running (up to 60 seconds)
system.mes.batch.queue.executeEntryCommand(
    entry,
    system.mes.batch.queue.COMMAND_START,
    changedBy='erpRelease.script'
)

deadline = time.time() + 60
while time.time() < deadline:
    status = system.mes.batch.queue.getStatus(entry)
    if status == 'Running':
        break
    if status in ('Aborted', 'Stopped', 'Internal Fault'):
        raise Exception('Batch failed to start: %s (%s)' % (entry.getBatchID(), status))
    time.sleep(0.5)
else:
    raise Exception('Batch did not reach Running: %s' % entry.getBatchID())

# Publish release confirmation
system.tag.writeBlocking(
    ['[default]ERP/BatchReleaseStatus', '[default]ERP/ActiveBatchID'],
    ['Running', entry.getBatchID()]
)
```


**Complex example 2** — manual-mode orchestration with valid next steps

Drive a semi-automatic workflow: start the batch, switch an operation to Manual mode, inspect valid active-step targets, change the active step, and execute the step when the operator (or script) is ready.
 
```python
import time

batchID = 'BATCH-MANUAL-007'
entry = system.mes.batch.queue.getEntry(batchID)
if entry is None:
    raise Exception('Batch not found: %s' % batchID)

changedBy = 'manualOrchestrator.script'
operationPath = '/{}/Crystallize/Grow Crystals'

# Start if still idle
if system.mes.batch.queue.getStatus(entry) == 'Idle':
    system.mes.batch.queue.executeEntryCommand(
        entry,
        system.mes.batch.queue.COMMAND_START,
        changedBy=changedBy
    )

# Wait until running
deadline = time.time() + 45
while time.time() < deadline:
    if system.mes.batch.queue.getStatus(entry) == 'Running':
        break
    time.sleep(0.25)
else:
    raise Exception('Batch not running: %s' % batchID)

# Put the operation in Manual so active steps can be selected
system.mes.batch.queue.setMode(
    entry,
    system.mes.batch.queue.MODE_MANUAL,
    operationPath,
    changedBy=changedBy
)

# Poll until valid next steps appear (recipe-dependent)
validSteps = []
deadline = time.time() + 30
while time.time() < deadline:
    validSteps = system.mes.batch.queue.getValidNextSteps(entry, operationPath)
    if validSteps:
        break
    time.sleep(0.5)

if not validSteps:
    raise Exception('No valid next steps under %s' % operationPath)

targetStep = validSteps[0]
logger = system.util.getLogger('batch.manual')
logger.info('Changing active step to %s' % targetStep)

system.mes.batch.queue.changeActiveStep(
    entry,
    targetStep,
    changedBy=changedBy
)

# Execute the now-active step in manual mode
system.mes.batch.queue.executeStep(
    entry,
    targetStep,
    changedBy=changedBy
)

activeSteps = system.mes.batch.queue.getActiveSteps(entry, operationPath)
logger.info('Active steps after execute: %s' % activeSteps)
```


### Complex example 3 — transition monitoring, skip, and batch messages 
 
Monitor pending transitions under a unit procedure, skip a blocking transition when an external readiness signal is true, and acknowledge operator messages for the same batch.
 
```python
import time

batchID = 'BATCH-XFER-015'
entry = system.mes.batch.queue.getEntry(batchID)
logicPath = '/{}/Transfer/Receive'
changedBy = 'transferSupervisor.script'
readinessTag = '[default]Transfer/ReadyToAdvance'

if system.mes.batch.queue.getStatus(entry) != 'Running':
    system.mes.batch.queue.executeEntryCommand(
        entry,
        system.mes.batch.queue.COMMAND_START,
        changedBy=changedBy
    )

logger = system.util.getLogger('batch.transfer')
deadline = time.time() + 120

while time.time() < deadline and system.mes.batch.queue.getStatus(entry) == 'Running':
    pending = system.mes.batch.queue.getPendingTransitions(entry, logicPath)

    for transition in pending:
        path = transition.getItemPath()
        overall = transition.getOverallStatus()
        logger.info('Pending transition %s (overall=%s)' % (path, overall))

        # External interlock says we may bypass the transition expression
        ready = system.tag.readBlocking([readinessTag])[0].value
        if ready and overall is not True:
            logger.warn('Skipping transition %s per external ready signal' % path)
            system.mes.batch.queue.skipTransition(
                entry,
                path,
                changedBy=changedBy
            )

    # Handle operator messages for this batch
    messages = system.mes.batch.queue.getMessages(entry)
    for msg in messages:
        if msg.getRequiresAcknowledgement() and not msg.isAcknowledged():
            logger.info('Acknowledging message: %s' % msg.getMessage())
            system.mes.batch.queue.acknowledgeMessage(msg)
        if msg.requiresValueEntry() and msg.getValue() is None:
            # Example: auto-fill a value prompt from a tag
            suggested = system.tag.readBlocking(['[default]Transfer/OperatorValue'])[0].value
            msg.setValue(suggested)
            system.mes.batch.queue.assignMessageValue(msg)

    if not pending:
        # No pending transitions — check whether the unit procedure finished
        status = system.mes.batch.queue.getTransitionStatus(
            entry, '/{}/Transfer/Receive:Complete Transition'
        )
        if status is not None and status.getOverallStatus() is True:
            logger.info('Transfer logic complete for %s' % batchID)
            break

    time.sleep(1.0)
```


## Related Functions 
 
Module: [system.mes.batch.queue](/articles/user-manual/system-mes-batch-queue)

| Function | Description |
| --- | --- |
| addEntry(...) | Create a queue entry from a master recipe or formula link. Returns a BatchQueueEntry. |
| addOrUpdateEntry(entry) | Add a new entry or update priority/unit assignments on an existing entry. |
| getEntry(batchID) | Return one BatchQueueEntry by batch ID. |
| getEntries(pageNumber, pageSize, searchPattern) | Return a filtered, paged list of queue entries. |
| getEntryLinks(...) | Return Batch Control Recipe links for queue entries. |
| getEntryCount(searchPattern) | Count entries matching a batch ID pattern. |
| removeEntry(entry) / removeEntry(batchID) | Remove an idle entry from the queue. |
| changeEntryPriority(entry, newPriority) | Change priority on an inactive entry. |
| assignUnit(entry, unitProcedurePath, unitEquipmentPath) | Assign a unit to a unit procedure. |
| getStatus(entry) / getStatus(batchID) | Authoritative batch execution state string. |
| executeEntryCommand(...) | Batch-level commands (Start, Hold, Reset, …). See executeEntryCommand-script.md. |
| setMode(...) | Set Auto / Semi-Auto / Manual on procedure logic. See setMode-script.md. |
| getValidNextSteps(...) | Valid manual active-step targets. See getValidNextSteps-script.md. |
| changeActiveStep(...) | Change the active step in manual logic. See changeActiveStep-script.md. |
| executeStep(...) | Execute the active step when parent logic is in Manual mode. |
| getPendingTransitions(...) / getTransitionStatus(...) | Inspect transition expressions. See [TransitionExpressionStatus-object.md](https://www.google.com/url?q=http://transitionexpressionstatus-object.md&amp;sa=D&amp;source=editors&amp;ust=1782923211690432&amp;usg=AOvVaw0z4aByBHOsEEQ9PzCe9BY8). |
| skipTransition(...) | Force a false transition to fire. |
| setParameterValue(...) / getParameterValue(...) | Read and write batch parameter values by item path. |
| getMessages(entry) | Batch messages for all units in the entry. |
| getBatchEBR(...) / getBatchBOM(...) | Export electronic batch record or bill of materials. |
| getExecutedBatchIDs(...) | Query historical batch IDs no longer in the queue. |

For the full API table, see batch-procedure-script-reference.md.
 
###  Related Objects and Components 
 
* BatchControlRecipe — Runtime recipe executed for this queue entry; loaded via entry.getRecipe().
* BatchMasterRecipe — Engineering template used when the batch was queued
* BatchFormula — Optional formula linked at queue time
* TransitionExpressionStatus — Transition evaluation snapshots for this entry during execution.
* Batch List — Operator queue UI (mes.batch.batchList); see batchList-component.md.
* Batch Controller — Step-level control bound to a batch ID and item path.
* Batch Recipe Monitor — Live SFC diagram for the entry's control recipe.

**Sepasoft MES Module Suite**