Making a File Upload Field Mandatory in a Zoho CRM Blueprint Transition

Sun Jun 21 2026
Zoho CRM · Blueprint · Client Scripts

Making a File Upload Field Mandatory in a Zoho CRM Blueprint Transition

Zoho CRM Blueprints control how records move through a process, but file upload fields cannot always be made mandatory directly inside a Blueprint transition. A practical workaround is to validate the saved file field with a Client Script before the transition continues.

Mostafa Badawy··7 min read

Workaround

  • Use a Client Script on the Blueprint beforeTransition event
  • Read the transition selected by the user
  • Fetch the current CRM record by ID
  • Return false when the required file is missing

Important limitation

  • The file must already be uploaded and saved on the record
  • This validates CRM UI transitions, not API-driven transitions
  • Use API names for the module and file upload fields

Example requirement

In this example, the Policies module contains three Blueprint transitions. Each transition requires a different file upload field before the user can continue.

Mark Policy Created

Required file field: Policy Document File

Save Amendment

Required file field: Amendment File

Mark Carrier Confirmed

Required file field: Carrier Confirmation File

If the required file field is empty, the user sees a clear error message and the Blueprint transition is stopped.

Client Script configuration

Create the Client Script with this setup:

  • Module: Policies
  • Page: Detail Page
  • Category: Blueprint Event
  • Event: beforeTransition
  • Layout: Select the layout used by the Blueprint

The transition argument is automatically available inside this event, so the same script can validate different required files for different transitions.

Client Script

var transitionName = "";

try {
    transitionName = transition.getName ? transition.getName() : transition.name;
} catch (e) {
    transitionName = "";
}

var recordId = $Page.record_id;
var policyRecord = ZDK.Apps.CRM.Policies.fetchById(recordId);

function isFileEmpty(fileValue) {
    if (fileValue == null || fileValue == undefined) {
        return true;
    }

    if (typeof fileValue == "string" && fileValue.trim() == "") {
        return true;
    }

    if (Array.isArray(fileValue) && fileValue.length == 0) {
        return true;
    }

    return false;
}

if (transitionName == "Mark Policy Created") {
    var policyFileValue = null;

    if (policyRecord.Policy_Document_File != undefined) {
        policyFileValue = policyRecord.Policy_Document_File;
    } else if (policyRecord._Policy_Document_File != undefined) {
        policyFileValue = policyRecord._Policy_Document_File;
    }

    log("Policy Document File Value:");
    log(policyFileValue);

    if (isFileEmpty(policyFileValue)) {
        ZDK.Client.showMessage(
            "Please upload and save the Policy Document File before marking the policy as created.",
            { type: "error" }
        );
        return false;
    }
}

if (transitionName == "Save Amendment") {
    var amendmentFileValue = null;

    if (policyRecord.Amendment_File != undefined) {
        amendmentFileValue = policyRecord.Amendment_File;
    } else if (policyRecord._Amendment_File != undefined) {
        amendmentFileValue = policyRecord._Amendment_File;
    }

    log("Amendment File Value:");
    log(amendmentFileValue);

    if (isFileEmpty(amendmentFileValue)) {
        ZDK.Client.showMessage(
            "Please upload and save the Amendment File before saving the amendment.",
            { type: "error" }
        );
        return false;
    }
}

if (transitionName == "Mark Carrier Confirmed") {
    var carrierFileValue = null;

    if (policyRecord.Carrier_Confirmation_File != undefined) {
        carrierFileValue = policyRecord.Carrier_Confirmation_File;
    } else if (policyRecord._Carrier_Confirmation_File != undefined) {
        carrierFileValue = policyRecord._Carrier_Confirmation_File;
    }

    log("Carrier Confirmation File Value:");
    log(carrierFileValue);

    if (isFileEmpty(carrierFileValue)) {
        ZDK.Client.showMessage(
            "Please upload and save the Carrier Confirmation File before confirming the policy.",
            { type: "error" }
        );
        return false;
    }
}

return true;

How the script works

  1. 1

    Identify the selected transition

    The script reads the transition name from transition.getName() when available, then falls back to transition.name.

  2. 2

    Fetch the current record

    The current Policy record is retrieved with $Page.record_id and ZDK.Apps.CRM.Policies.fetchById(recordId).

  3. 3

    Check whether the file is empty

    The helper treats null, undefined, empty strings, and empty arrays as missing values.

  4. 4

    Block the transition

    When the required file is missing, the script shows an error message and returns false to prevent the transition from completing.

Important notes

  • The file must be uploaded and saved on the record before the transition is selected. Because the script uses fetchById(), it reads the saved CRM record, not an unsaved file currently being added to the page.
  • Replace Policies, the Blueprint transition names, file upload field API names, and error messages before using this in another module.
  • The underscore-prefixed field checks are included as a fallback. Use the Client Script logs to confirm the exact property name returned in your CRM environment.
  • Client Scripts run in the CRM interface. If the Blueprint transition is executed through an API or another server-side process, add separate server-side validation.
Using the Blueprint beforeTransition event gives users a clear message, prevents incomplete records from progressing, and allows multiple transitions and file fields to be controlled from one Client Script.