Get the Current Record ID in a NetSuite Client Button

Replace an unavailable button callback context with N/currentRecord.get(), guard a new unsaved record and verify a read-only item-ID request locally.

The quick answer

In a custom button handler invoked without an entry-point context, import N/currentRecord, call currentRecord.get(), then read the returned object's id. Guard against a missing saved ID before passing it to a receiver.

Before you start

This walkthrough is a synthetic local exercise. Actual source bytes execute against explicit currentRecord, https and record stand-ins. The prepared item page uses a bounded source adapter and a real local HTTP receiver. It does not execute arbitrary uploaded JavaScript or demonstrate an account deployment.

The saved Inventory Item is Copper Coupler, internal ID 2147, base unit Each. Its Inspect Item ID button, beforeLoad attachment, exported inspectItem handler and internal-receiver configuration are already prepared. The handler runs in the client UI and imports N/currentRecord; the prepared beforeLoad configuration attaches its client file to this form. currentRecord.get() is not a server-side replacement for context.newRecord. Creating and deploying those objects is outside the recording.

The original forum question also asked about opening a new window and saving the ID in a Suitelet field. This lesson stops at read-only ID retrieval and transmission. It creates no window, item or business-record update.

Oracle distinguishes Client Script entry-point context from custom module access. A native account also needs an applicable attachment, authenticated internal Suitelet deployment, audience and permissions. The local result verifies none of those account prerequisites.

01 · Inspect the callback

Open the saved local item. Confirm Internal ID 2147 and Copper Coupler before opening its client source.

Copper Coupler already has saved Internal ID 2147. Enlarge for the prepared item button and full record.

The initial function expects a context argument:

function inspectItem(context) {
  const active = context.currentRecord;
  const itemId = active.id;

Click Run local harness. This custom-button setup invokes the exported function without arguments, so reading context.currentRecord throws TypeError in the local JavaScript execution. This is a synthetic source editor, not a native browser console.

The handler reads context.currentRecord even though this button supplies no entry-point argument. Enlarge for the actual local TypeError.

02 · Read the saved ID

Remove the unused callback parameter and obtain the active record through the imported module:

function inspectItem() {
  const active = currentRecord.get();
  const itemId = active.id;

The existing define call already imports N/currentRecord. Keep the exported handler, saved-ID guard and request routing unchanged. Oracle documents currentRecord.get() and the read-only CurrentRecord.id property.

The corrected handler calls currentRecord.get() and reads active.id. The imported module and exported handler remain in place.

Click Save, then Run local exercise. The actual saved source runs with the saved-item stand-in and updates the prepared local attachment. In the local stand-ins, its output reports ID 2147, GET custparam_itemid=2147, and receiver 2147 / Copper Coupler.

Actual saved source uses ID 2147 in custparam_itemid and receives Copper Coupler from explicit local stand-ins.

The request uses https.requestSuitelet with GET and this urlParams portion of the complete prepared request:

urlParams: {
  custparam_itemid: String(itemId)
}

https.requestSuitelet calls an internal Suitelet in a trusted authenticated context. It does not require an anonymous external deployment.

03 · Check the guard and receiver

Click Run unsaved-record model. This separate stand-in uses a null ID. The existing guard displays its save-first message and returns before making a request:

if (!itemId) {
  window.alert(
    'Save this inventory item ' +
    'before using this action.'
  );
  return;
}

The message is the same as the recorded single-line literal. This does not change Copper Coupler. The null value is an explicit local stand-in, not a claim about every native empty-ID representation.

The separate null-ID model issues zero requests. Its full output contains the save-first message; it does not change the saved item.

Open the read-only item_identity_receiver.js preview. It validates custparam_itemid as a positive integer and loads record.Type.INVENTORY_ITEM. The response string inventoryitem identifies that record type; Inventory Item is the UI label.

The receiver loads the intended record.Type.INVENTORY_ITEM after validating its positive integer parameter. Enlarge for the full read-only source.

The receiver calls record.load, getValue and response.write. It has no save or submitFields operation. Query input is untrusted: a positive ID and record-type check are not complete production authorization. Do not add a write operation based solely on a submitted ID.

04 · Verify the local item button

Return to Copper Coupler and click Inspect Item ID. The bounded item adapter sends an actual local HTTP GET. Its read-only response contains:

{
  "itemId": 2147,
  "recordType": "inventoryitem",
  "itemName": "Copper Coupler"
}
The actual local GET acknowledgment returns itemId 2147, inventoryitem and Copper Coupler. No account Suitelet or business-record save ran.

Dismiss the acknowledgment, reload the same item and repeat once. Dismiss it again and confirm 2147, Copper Coupler and base unit Each remain unchanged. This checks retained local wiring and identity; it does not establish account Suitelet execution or saving another record.

Common questions

Why is context.currentRecord unavailable here?

This custom-button invocation supplies no scriptContext argument. A supported native Client Script entry point receives its documented context; this exported custom function obtains the active record through N/currentRecord instead.

Is CurrentRecord.id the item name?

No. It is the saved record's read-only internal ID. Copper Coupler is the display name in this example. Keep the intended record type with the ID when a receiver loads a record.

Does an edited saved record lose its ID?

No. Editing an already saved record retains its existing ID. A newly created record or copy before its first save is a separate case; guard against a missing usable saved ID before issuing the request.

Can I pass the ID through an internal Suitelet query parameter?

Yes, the example uses GET urlParams and context.request.parameters. The identified Suitelet must be deployed, and the current user's access still matters. Validate the parameter and intended type; do not treat client input as authorization to update a record.

Does this show the Suitelet saving the ID in a field?

No. The receiver reads the item and returns JSON. The original new-window and field-persistence requirements need their own tested workflow; neither is demonstrated by this local acknowledgment.