DocsReference

Deluge lint rules

Zenith checks every Deluge draft against 80 rules before anything is pushed to Zoho Creator: 45 errors, 25 warnings and 10 notes. 23 of them are checked against your app's own forms and fields.

From Zenith's built-in Creator knowledge pack, version 1.0.0 (2026-10-10). Rule ids are stable, so you can refer to them in your project rules, code reviews and tickets.

Syntax 9

DLG000 Error

Syntax error

The code does not parse: unbalanced brackets, an unterminated string or comment, or a token Deluge can't accept here. When Zenith's parser is only unsure (a construct it does not know), the finding is a warning; Creator's compiler has the final say.

Example

Fails

if(x > 1)
{
	info x;

Works

if(x > 1)
{
	info x;
}
DLG005 Error

No comments inside insert/update blocks or multi-line call arguments

Comments inside insert into X [ … ] or update … [ … ] blocks, or between the arguments of a multi-line call, have caused 'Improper Statement' save errors. Put comments before the statement.

Example

Fails

new_id = insert into Orders
[
	Customer = customer_id_param
	// default status
	Status = "Open"
];

Works

// default status is Open
new_id = insert into Orders
[
	Customer = customer_id_param
	Status = "Open"
];
DLG011 Error

Smart quotes and look-alike punctuation

Curly quotes (“ ” ‘ ’), full-width semicolons and similar characters pasted from documents break parsing outside string literals.

Example

Fails

status_value = “Open”;

Works

status_value = "Open";
DLG012 Error

Missing semicolon

Every statement ends with ; (Creator: 'Improper Statement Error might be due to missing ';' …'). Creator often reports the line after the one that is missing it.

Example

Fails

total = 0
info total;

Works

total = 0;
info total;

Zoho docs: Deluge error messages

DLG016 Error

No ?: ternary: use if(cond, a, b)

Deluge has no ternary operator. The conditional if(condition, a, b) function returns one of two values.

Example

Fails

label = order_total > 1000 ? "Large" : "Standard";

Works

label = if(order_total > 1000, "Large", "Standard");

Zoho docs: Conditional statements

DLG017 Error

No ++ / --: use += 1 or x = x + 1

Deluge has no increment or decrement operators. Compound assignment (+=, -=, *=, /=, %=) is supported.

Example

Fails

processed++;

Works

processed += 1;

Zoho docs: Assignment operators

DLG031 Error

String literal ending in a backslash

A string whose last character is \ escapes its own closing quote, which Creator reports as Improper Statement. Don't end a literal with a backslash; to end text with one, build it with "5c".hexToText() and concatenate. Inside a literal, Zoho's regex examples write one backslash as \\.

Example

Fails

separator_text = "\";

Works

backslash_char = "5c".hexToText();
windows_path = "C:" + backslash_char + "exports" + backslash_char;

Zoho docs: Deluge error messages

DLG033 Error

JavaScript/Python-style APIs that don't exist in Deluge

APIs that look right but don't exist in Deluge: .forEach, .map, .filter, .push, .append(…), .length without parentheses, JSON.parse/JSON.stringify, console.log, print(), pow(), Math.*, str(), len(x) on lists. Use for each, .add(), .size(), toMap()/toString(), info, power(), and .length() on text.

Example

Fails

items.push(order_id);
payload = JSON.stringify(order_map);

Works

items.add(order_id);
payload = order_map.toString();

Zoho docs: Built-in functions

DLG042 Error

No namespace blocks, lambdas or nested function definitions

Functions are created one per editor entry (Namespace.Name in the signature). namespace X { … }, function(…) { … } lambdas and functions declared inside functions don't exist.

Example

Fails

namespace Orders
{
	void Close(int order_id_param)
	{
		info order_id_param;
	}
}

Works

void Orders.Close(int order_id_param)
{
	info order_id_param;
}

Control flow 6

DLG001 Error

No while / do-while loops

Deluge has no while or do-while statement. Replace it with a bounded for each over a slot list (or a literal list) and break when done.

Example

Fails

while(has_more)
{
	page = page + 1;
}

Works

slots = leftpad("1", 50).replaceAll(" ", "1,").toList(",");
has_more = true;
for each index page_index in slots
{
	if(!has_more)
	{
		break;
	}
	has_more = false;
}

Zoho docs: for each element

DLG002 Error

No C-style or range-style for loops

for (i = 0; …), for i in range(n) and for i in 0..n do not exist. Use for each over a list, or for each index over a list for positions.

Example

Fails

for (i = 0; i < items.size(); i = i + 1)
{
	info items.get(i);
}

Works

for each index i in items
{
	info items.get(i);
}

Zoho docs: for each element

DLG024 Error

No sleep()/wait(): schedule instead

Deluge has no sleep, wait or delay function. Spread work over time with a Run_At date-time on a queue record (form schedule) or the next scheduled run.

Example

Fails

for each order_rec in batch_orders
{
	thisapp.Orders.Push_To_Fulfillment(order_rec.ID);
	sleep(500);
}

Works

offset_seconds = 0;
for each order_rec in batch_orders
{
	offset_seconds += 10;
	order_rec.Push_At = zoho.currenttime.addSeconds(60 + offset_seconds);
}

Zoho docs: Built-in functions

DLG025 Error

No switch/case: use if / else if

Deluge has no switch statement; chain if / else if / else, or map a key to a value with a Map.

Example

Fails

switch(status_value)
{
	case "Open":
		label = "Active";
}

Works

label_by_status = {"Open":"Active","Closed":"Done"};
label = ifnull(label_by_status.get(status_value), "Other");

Zoho docs: Conditional statements

DLG027 Warning

for each index yields positions, not values

for each index i in L sets i to 0…L.size()-1. Iterating a computed range (for example a Range(5, 10) helper) with for each index processes positions 0…4, not 5…9. Use for each v in L for values; use index only with L.get(i).

Example

Fails

for each index i in thisapp.Util.Range(5, 10)
{
	info items.get(i);
}

Works

for each i in thisapp.Util.Range(5, 10)
{
	info items.get(i);
}

Zoho docs: for each index

DLG052 Warning

Mixed && and || without parentheses in a condition (Creator: OR binds tighter)

Creator's documented logical precedence is NOT > OR > AND (other Zoho services and most languages put AND before OR), so if(a && b || c) means a && (b || c) in Creator. Parenthesize every group where && and || meet at the same level of an if, else if or conditional if(). There is no automatic fix: only the author knows the grouping they meant.

Example

Fails

if(order_status == "Open" && order_total > 1000 || is_priority == true)
{
	info "review";
}

Works

if((order_status == "Open" && order_total > 1000) || is_priority == true)
{
	info "review";
}

Zoho docs: Logical operators, Criteria in conditions

Functions 9

DLG004 Error

Typed function needs a return after try/catch / if-chains

A function with a non-void return type must end with a return statement reachable on every path; returns inside try and catch are not enough (Creator: 'Missing return statement: Provide <TYPE> expression to return').

Example

Fails

int Orders.Count_Open(int customer_id_param)
{
	try
	{
		return Orders[Customer == customer_id_param].count();
	}
	catch (e)
	{
		return -1;
	}
}

Works

int Orders.Count_Open(int customer_id_param)
{
	try
	{
		return Orders[Customer == customer_id_param].count();
	}
	catch (e)
	{
		info e.message;
	}
	return -1;
}

Zoho docs: Deluge error messages

DLG019 Error

No default or optional parameters

Function parameters can't have default values and functions can't be overloaded; every call must pass exactly the declared arguments.

Example

Fails

map Orders.Search(string status_param = "Open", int limit_param = 50)
{
	return Map();
}

Works

map Orders.Search(string status_param, int limit_param)
{
	result = Map();
	result.put("count", Orders[Status == status_param].count());
	return result;
}

Zoho docs: Deluge error messages

DLG020 Error

Signature must be line 1 of a function file

Nothing (comments, blank lines, export headers) may come before <type> Namespace.Name(...). Put docs inside the body.

Example

Fails

// Function: Orders.Close
// Exported: 2026-01-01
void Orders.Close(int order_id_param)
{
	info order_id_param;
}

Works

void Orders.Close(int order_id_param)
{
	// Closes one order. Params: order_id_param = Orders.ID
	info order_id_param;
}
DLG021 Error

No datetime type in signatures

datetime is not a Deluge type (Creator: 'Form 'datetime' does not exist'). Use date for date and date-time parameters and return types.

Example

Fails

string Tasks.Describe(datetime due_at_param)
{
	return due_at_param.toString("dd-MMM-yyyy HH:mm");
}

Works

string Tasks.Describe(date due_at_param)
{
	return due_at_param.toString("dd-MMM-yyyy HH:mm");
}
DLG104 Error Checks your app's schema

Call argument count must match the signature

There are no optional parameters: thisapp.NS.Fn(...) must pass exactly the declared number of arguments. On code Creator already saved (the mirror) it is reported as a warning: the caller saved against an older signature (Creator does not re-check callers) and fails when it runs or is saved again.

Example

Fails

summary = thisapp.Invoices.Build_Summary(invoice_id);

Works

summary = thisapp.Invoices.Build_Summary(invoice_id, false);

Zoho docs: Deluge error messages

DLG105 Error Checks your app's schema

Called function doesn't exist (yet)

Calling a function that doesn't exist fails to save (Creator: 'Not able to find … function'). It must exist in the app or be created earlier in the same deploy.

Example

Fails

thisapp.Orders.Recalc_Totals(order_id_param);

Works

thisapp.Orders.Recalculate_Totals(order_id_param);

Zoho docs: Deluge error messages

DLG106 Error Checks your app's schema

Signature change without updating every caller

Changing the parameters of an existing function breaks every caller (functions, workflows, schedules, custom actions, report and lookup filters, pages). Update all callers in the same change and push the callee first.

Example

Fails

// feature changes Invoices.Build_Summary(int) to (int, bool) but leaves this caller:
summary = thisapp.Invoices.Build_Summary(invoice_id);

Works

summary = thisapp.Invoices.Build_Summary(invoice_id, false);
DLG114 Warning Checks your app's schema

Result of a value-returning call is ignored

Creator saves bare calls of value-returning app functions (hundreds of them in production code), so those are only an info hint. A bare call of a pure built-in (text.trim();, ifnull(a, b);) does nothing and is a warning.

Example

Fails

thisapp.Invoices.Build_Summary(invoice_id, false);

Works

summary = thisapp.Invoices.Build_Summary(invoice_id, false);

Zoho docs: Deluge error messages

DLG115 Error Checks your app's schema

Void function assigned or used in an expression

Assigning the result of a void function fails to save (Creator: '… cant be assigned to variable or used in expression'). On code Creator already saved (the mirror) it is reported as a warning: the caller saved before the callee became void and fails when it runs or is saved again.

Example

Fails

result = thisapp.Orders.Close(order_id_param);

Works

thisapp.Orders.Close(order_id_param);

Zoho docs: Deluge error messages

Criteria 9

DLG009 Warning

Don't mix && and || in one fetch criteria

Creator's documented precedence is NOT > OR > AND (other Zoho apps differ), and parentheses have been seen not to apply inside Form[...] criteria. Same-field ORs: use in {}; cross-field ORs: separate fetches, or filter in code. Mixed criteria save and run in Creator; this flags a precedence hazard, not a save error.

Example

Fails

open_orders = Orders[Customer == customer_id_param && (Status == "Open" || Status == "On Hold")];

Works

open_orders = Orders[Customer == customer_id_param && Status in {"Open","On Hold"}];

Zoho docs: Logical operators

DLG018 Error

No .limit() / .maxRecords() / limit-offset: use range

Limit fetched rows with range from a to b (inclusive; 0 and 1 both mean the first record), after any sort by.

Example

Fails

stale_runs = Runs[Status == "Active"].limit(50);

Works

stale_runs = Runs[Status == "Active"] sort by ID range from 1 to 50;

Zoho docs: Fetch records

DLG023 Error

null can't be an element of in {}

Fetch without the null alternative and filter in code, or run a second fetch with Field == null.

Example

Fails

orders = Orders[Status in {"Open", null}];

Works

open_orders = Orders[Status == "Open"];
unset_orders = Orders[Status == null];
DLG051 Warning

List literal with more than six elements in criteria

Zoho documents that LIST expressions in criteria cannot hold more than six elements. Keep literal in {…} sets to six or fewer, or move the values to a variable or lookup and test it in a sandbox.

Example

Fails

orders = Orders[Status in {"New","Open","Held","Review","Approved","Packed","Shipped"}];

Works

active_statuses = {"New","Open","Held","Review","Approved","Packed","Shipped"};
orders = Orders[Status in active_statuses];

Zoho docs: Criteria

DLG101 Error Checks your app's schema

Criteria variable shadows a field of the queried form

Inside Form[...], an identifier equal to a field link name of that form refers to the field, not your variable or parameter, so Orders[ID == order_id] compares the field order_id to itself. Rename variables used in criteria (suffix _param, _value or _filter). On code Creator already saved (the mirror) it is reported as a warning: the filter silently matches every record; fix it when you next touch the function.

Example

Fails

void Orders.Close(int order_id)
{
	order = Orders[ID == order_id];
}

Works

void Orders.Close(int order_id_param)
{
	order = Orders[ID == order_id_param];
}
DLG107 Error Checks your app's schema

Multi-select lookup membership uses Field.contains(id)

Form[Multi contains x] and Form[x in Multi] fail for multi-select lookups. Use Form[Multi.contains(record_id)] (the production idiom) with a Creator record ID. Zoho's criteria table documents ==, !=, in and not in with a LIST of record IDs on the field side (Form[Multi in id_list]); both forms are acceptable. Never put the field on the right of in.

Example

Fails

orders = Orders[Products contains product_id_param];

Works

orders = Orders[Products.contains(product_id_param)];
DLG116 Error Checks your app's schema

Text methods on a lookup value

Lookup fields hold record IDs (numbers). Calling .contains("…") or .startsWith on them, or comparing them to display text, is invalid. Compare IDs or traverse to a text field.

Example

Fails

acme_orders = Orders[Customer.contains("Acme")];

Works

acme_orders = Orders[Customer.Company_Name.contains("Acme")];
DLG124 Error Checks your app's schema

Unsupported operator on an encrypted field

Fields with data encryption support only ==, != and isEmpty() in criteria.

Example

Fails

matches = Customers[Tax_Number.startsWith("12")];

Works

matches = Customers[Tax_Number == tax_number_param];

Zoho docs: Criteria

DLG125 Error Checks your app's schema

sort by a field that can't be sorted

Records can't be sorted by Multi Select, Multi Select lookup, Checkbox, subform, Name or Address (composite) fields, nor by Added_Location or Modified_Location.

Example

Fails

orders = Orders[Status == "Open"] sort by Products;

Works

orders = Orders[Status == "Open"] sort by Order_Date desc;

Zoho docs: Fetch records

Records 5

DLG029 Warning

update Form[criteria] [...] updates only the first match

The update-multiple-fields task on a filtered form updates the first matching record only. Use an ID criteria, or loop over the records.

Example

Fails

update Orders[Status == "Open" && Due_Date < zoho.currentdate]
[
	Status = "Overdue"
];

Works

for each late_order in Orders[Status == "Open" && Due_Date < zoho.currentdate]
{
	update late_order
	[
		Status = "Overdue"
	];
}

Zoho docs: Update multiple fields

DLG030 Error

Don't write system or computed fields

ID, Added_Time, Modified_Time, Modified_User, the IP and location system fields, Auto Number and Formula fields are set by Creator and can't be assigned in insert or update or with rec.Field = …. There is no Created_At system field.

Example

Fails

order.Modified_Time = zoho.currenttime;

Works

order.Last_Reviewed_At = zoho.currenttime;

Zoho docs: Add records, Update records

DLG117 Error Checks your app's schema

insert without every mandatory field

An insert must supply every mandatory field of the target form or it fails at runtime.

Example

Fails

new_id = insert into Orders
[
	Status = "Open"
];

Works

new_id = insert into Orders
[
	Customer = customer_id_param
	Order_Date = zoho.currentdate
	Status = "Open"
];

Zoho docs: Add records

DLG118 Error Checks your app's schema

Write to an Auto Number, Formula or other read-only field

Auto Number, Formula and Signature fields can't be set from Deluge; Add Notes fields can't be written by insert or update or on a fetched record, and subform fields can't be set by an update. A form workflow may rewrite an Add Notes field on screen with input.<Note_Field> = "…" (not flagged).

Example

Fails

order_rec.Order_Number = "ORD-1001";

Works

order_rec.External_Ref = "ORD-1001";

Zoho docs: Update records

DLG119 Warning Checks your app's schema

Writing a value that isn't a configured choice

Deluge writes to Drop Down, Radio and Multi Select fields accept any text and store it silently (the choice isn't added to the field). A literal that isn't one of the field's choices is usually a typo.

Example

Fails

order_rec.Status = "Shiped";

Works

order_rec.Status = "Shipped";

Zoho docs: Add records

Collections 5

DLG010 Error

Sort record collections with sort by, not .sort()

A fetch is sorted in the fetch itself: Form[criteria] sort by Field [desc]. .sort(…) is a List method.

Example

Fails

recent = Orders[Customer == customer_id_param].sort(Order_Date, false);

Works

recent = Orders[Customer == customer_id_param] sort by Order_Date desc;

Zoho docs: Fetch records

DLG022 Error

List("a","b") is not a list constructor

List() creates an empty list; List(text) splits one comma-separated text. Use a literal {"a","b"} for known elements.

Example

Fails

statuses = List("Open", "On Hold");

Works

statuses = {"Open","On Hold"};

Zoho docs: Create a list

DLG109 Warning Checks your app's schema

.size() for lists, .count() for record collections

Multi-select and multi-lookup values and other lists use .size(); fetch results use .count(). Mixing them errors (Creator: 'Collection expected, found List').

Example

Fails

if(order_rec.Products.count() > 0)
{
	info "has products";
}

Works

if(order_rec.Products != null && order_rec.Products.size() > 0)
{
	info "has products";
}
DLG111 Warning Checks your app's schema

Dot access on a Map

Maps (Map(), {…}, toMap(), JSON responses) are read with .get("key"); m.key is invalid. Dot access is for records.

Example

Fails

response_map = response_text.toMap();
status_value = response_map.status;

Works

response_map = response_text.toMap();
status_value = response_map.get("status");
DLG126 Info Checks your app's schema

Iterating a multi-select lookup field as if it held records

A multi-select lookup field is a list of record IDs. Iterating it yields IDs; fetch the records with Form[ID in rec.Field] first. Production code reads fields of the loop variable while iterating a multi-select lookup; verify before rewriting.

Example

Fails

for each product_rec in order_rec.Products
{
	info product_rec.Product_Name;
}

Works

for each product_rec in Products[ID in order_rec.Products]
{
	info product_rec.Product_Name;
}

Strings 6

DLG006 Error

No .split(): use toList(separator)

Text has no split() method. text.toList(sep) splits; getPrefix, getSuffix, indexOf and subString cover single cuts.

Example

Fails

parts = email_text.split("@");

Works

parts = email_text.toList("@");

Zoho docs: toList()

DLG026 Error

urlEncode() is zoho.encryption.urlEncode()

A bare urlEncode(x) call fails (Creator: 'Not able to find 'urlEncode' function'). Use zoho.encryption.urlEncode(x) (space becomes %20) or encodeUrl(x) (space becomes +).

Example

Fails

link = "#Report:All_Orders?Status=" + urlEncode(status_value);

Works

link = "#Report:All_Orders?Status=" + zoho.encryption.urlEncode(status_value);

Zoho docs: zoho.encryption.urlEncode(), encodeUrl()

DLG028 Warning

replaceAll treats the search text as a regex

replaceAll and replaceFirst use regular expressions by default; . matches any character and +, *, ?, (, [, |, $, ^, \ are metacharacters. Pass true as the third argument for a literal search.

Example

Fails

safe_name = file_name.replaceAll(".", "_");

Works

safe_name = file_name.replaceAll(".", "_", true);

Zoho docs: replaceAll()

DLG048 Warning

getPrefix/getSuffix return null when the separator is missing

Chaining a method on getPrefix() or getSuffix() fails at runtime when the separator isn't there (Creator: 'Null value occurred…'). Check for null or wrap it with ifnull.

Example

Fails

domain = email_text.getSuffix("@").toLowerCase();

Works

domain = ifnull(email_text.getSuffix("@"), "").toLowerCase();

Zoho docs: getSuffix()

DLG050 Warning

subString/left/right with a fixed bound on variable text

subString(start, end) errors when an index is past the end of the text (Creator: 'Given string is lesser than the applied boundary…'). Clamp it with min(text.length(), n).

Example

Fails

preview = body_text.subString(0, 500);

Works

preview = body_text.subString(0, min(body_text.length(), 500));

Zoho docs: subString()

DLG053 Warning

zoho.encryption.urlDecode() is not available in Creator

Zoho documents urlDecode as unavailable in Creator, but zoho.encryption.urlDecode() saves in Creator code that runs in production. Verify it at runtime, or avoid needing it: keep raw values unencoded and encode only at the boundary.

Example

Fails

status_value = zoho.encryption.urlDecode(encoded_status);

Works

link = "#Page:Order_Dashboard?status_filter=" + zoho.encryption.urlEncode(status_value);

Zoho docs: zoho.encryption.urlDecode()

Numbers 1

DLG007 Error

round() needs a precision argument

round is a method that needs the number of digits: x.round(0), x.round(2). x.round() and round(x) fail.

Example

Fails

total = subtotal.round();

Works

total = subtotal.round(2);

Zoho docs: round()

Dates and times 3

DLG008 Error

Date-time methods that don't exist

toStartOfDay, startOfDay, truncate, setHour, withTime, midnight, minutesBetween and secondsBetween do not exist. Midnight: d.toString("dd-MMM-yyyy").toDateTime(); elapsed minutes: ((b.toLong() - a.toLong()) / 60000).toLong().

Example

Fails

minutes_open = opened_at.minutesBetween(zoho.currenttime);
day_start = zoho.currenttime.toStartOfDay();

Works

minutes_open = ((zoho.currenttime.toLong() - opened_at.toLong()) / 60000).toLong();
day_start = zoho.currenttime.toString("dd-MMM-yyyy").toDateTime();

Zoho docs: Date-time functions

DLG015 Error

Date-time method singular/plural spelling

addDay, addHour, addWeek, addMonth, addYear and subDay, subHour, … are singular; addMinutes, addSeconds, subMinutes and subSeconds are plural. addMinute, addDays, addHours, addSecond, subDays, subHours, subMinute, addWeeks, addMonths and addYears don't exist.

Example

Fails

remind_at = zoho.currenttime.addMinute(30);
due_at = zoho.currenttime.addDays(3);

Works

remind_at = zoho.currenttime.addMinutes(30);
due_at = zoho.currenttime.addDay(3);

Zoho docs: Date-time functions

DLG108 Error Checks your app's schema

Date/Date-Time compared with ""

Date values are null or a date; comparing them to "" is a type mismatch. Check != null only.

Example

Fails

if(order_rec.Due_Date != null && order_rec.Due_Date != "")
{
	info "has due date";
}

Works

if(order_rec.Due_Date != null)
{
	info "has due date";
}

Types 1

DLG049 Warning

Same variable reused for records of different forms

Reusing one variable for fetches from different forms in one function has produced 'Improper Statement' errors and confusing behavior. Use a distinct name per form.

Example

Fails

rec = Orders[ID == order_id_param];
info rec.Status;
rec = Invoices[Order == order_id_param];
info rec.Total;

Works

order_rec = Orders[ID == order_id_param];
info order_rec.Status;
invoice_rec = Invoices[Order == order_id_param];
info invoice_rec.Total;

Schema 2

DLG102 Error Checks your app's schema

Field not found on the form (case-sensitive)

Field link names are case-sensitive and must exist on the form (Creator: 'Variable … is not defined'). Remember Creator's _field suffix for reserved names (Type_field, Subject_field).

Example

Fails

status_value = order_rec.status;

Works

status_value = order_rec.Status;
DLG103 Error Checks your app's schema

Form not found

Fetch, insert, update and delete targets must be existing form link names (deploy forms before functions).

Example

Fails

recent = Order[Status == "Open"];

Works

recent = Orders[Status == "Open"];

Pages 5

DLG043 Error

No HTML or <% %> in a page script

The page script is pure Deluge; markup and <% %> templating belong in the HTML snippet element.

Example

Fails

open_count = Orders[Status == "Open"].count();
<div><%=open_count%></div>

Works

open_count = Orders[Status == "Open"].count();
DLG044 Warning

A // comment must not run up to %> in an HTML snippet

Inside <% %> blocks of an HTML snippet, a // comment that runs up to the closing %> on the same line can swallow the code Creator generates after the block (Creator: 'Improper Statement (missing ;)'). A // comment on its own line inside a multi-line block saves and runs; end the comment with a line break, or use /* */.

Example

Fails

<%{%>
<%
for each row_map in input.status_rows
{ // one row per status %>
<li><%=row_map.get("status")%></li>
<%
}
%>
<%}%>

Works

<%{%>
<%
for each row_map in input.status_rows
{ /* one row per status */ %>
<li><%=row_map.get("status")%></li>
<%
}
%>
<%}%>
DLG045 Warning

HTML snippet with Deluge blocks lacks the <%{%> … <%}%> wrapper

Some apps need the whole snippet wrapped in <%{%> … <%}%> for <% %> blocks to run. Add it when a snippet contains Deluge blocks.

Example

Fails

<ul>
<% for each row_map in input.status_rows { %>
<li><%=row_map.get("status")%></li>
<% } %>
</ul>

Works

<%{%>
<ul>
<% for each row_map in input.status_rows { %>
<li><%=row_map.get("status")%></li>
<% } %>
</ul>
<%}%>
DLG046 Warning

Page script input.* values are read-only

In page scripts, input.<var> holds page variables and URL parameters; copy it into a local variable before transforming it. (HTML and ZML snippets may assign input.<param> inside <% %> to give a parameter a default and read it back with <%=input.param%>; that saves and runs, so snippets are not flagged.)

Example

Fails

input.status_filter = "Open";

Works

status_value = ifnull(input.status_filter, "Open");
DLG047 Warning

List methods on collection page variables

Collection page variables don't distinguish lists and maps; .add() and .remove() on them fail (Creator: '…applicable for LIST expression, but … is of type COLLECTION'). Build a local List() or Map() and assign it to the page variable at the end.

Example

Fails

status_rows.add("Open");

Works

rows_local = List();
rows_local.add("Open");
status_rows = rows_local;

Workflows 4

DLG032 Error

Client functions only in form events

alert, hide, show, enable, disable, clear, select/deselect, :ui.add, cancel submit, openUrl and reload work in form events (load, user input, validate, field rules). They are invalid in custom functions, schedules, batch workflows and page scripts.

Example

Fails

void Orders.Recalculate(int order_id_param)
{
	alert "Recalculated";
}

Works

void Orders.Recalculate(int order_id_param)
{
	info "Recalculated " + order_id_param;
}

Zoho docs: Client functions: alert

DLG120 Info Checks your app's schema

Deluge insert skips the target form's On Validate / On Success

Records created with insert into don't run the target form's On Validate and On Success workflows. If that form has such workflows, call their shared function explicitly.

Example

Fails

new_id = insert into Orders
[
	Customer = customer_id_param
	Status = "Open"
];

Works

new_id = insert into Orders
[
	Customer = customer_id_param
	Status = "Open"
];
thisapp.Orders.After_Save(new_id);

Zoho docs: Add records

DLG121 Warning Checks your app's schema

A date-field schedule's run edits its own trigger field

A 'once' schedule on a Date-Time field does not reschedule when its own run modifies that field (documented). Arm the next run by inserting a new record (a queue item or step row), or let a separate sweeper re-arm it.

Example

Fails

void Tasks.Send_Reminder(int task_id_param)
{
	task_rec = Tasks[ID == task_id_param];
	task_rec.Remind_At = zoho.currenttime.addDay(1);
}

Works

void Tasks.Send_Reminder(int task_id_param)
{
	task_rec = Tasks[ID == task_id_param];
	task_rec.Reminder_Status = "Sent";
	next_id = insert into Task_Reminders
	[
		Task = task_id_param
		Remind_At = zoho.currenttime.addDay(1)
		Reminder_Status = "Scheduled"
	];
}
DLG122 Warning Checks your app's schema

Trigger time set to now (or the past)

Date-field triggers set to zoho.currenttime can be missed if the record saves after that instant, and past values may never fire. Use at least zoho.currenttime.addMinutes(1) and pair it with a stale sweeper.

Example

Fails

item_rec.Run_At = zoho.currenttime;

Works

item_rec.Run_At = zoho.currenttime.addMinutes(1);

Integrations 1

DLG034 Error

sendmail sender must be admin, login user or verified

from must be zoho.adminuserid, zoho.loginuserid (not portal users) or a verified address; otherwise the save fails (literal) or the run fails (variable). With another sender, to may only be zoho.adminuserid and cc/bcc are not allowed. from, to, subject and message are mandatory.

Example

Fails

sendmail
[
	from: "billing@example.com"
	to: customer_email
	cc: "manager@example.com"
	subject: "Invoice"
	message: "Attached"
]

Works

sendmail
[
	from: zoho.adminuserid
	to: customer_email
	cc: "manager@example.com"
	subject: "Invoice"
	message: "Attached"
]

Zoho docs: Send mail

Security 5

DLG035 Warning

No credentials in invokeurl URLs

Credentials embedded in invokeurl URLs (user:pass@host, api_key, token or secret query parameters) were deprecated on 2025-09-30. Use a Connection (connection: "name").

Example

Fails

response = invokeurl
[
	url: "https://api.example.com/v1/orders?api_key=abc123"
	type: GET
];

Works

response = invokeurl
[
	url: "https://api.example.com/v1/orders"
	type: GET
	connection: "example_api"
];

Zoho docs: Deluge release notes, Connections

DLG036 Warning

Authorization headers built in code instead of a Connection

Setting Authorization or X-API-Key headers yourself means a credential lives in code or data. Prefer a Connection (OAuth 2, API key, Basic, AWS SigV4) and pass connection:.

Example

Fails

headers = Map();
headers.put("Authorization", "Bearer " + api_token);
response = invokeurl
[
	url: "https://api.example.com/v1/orders"
	type: GET
	headers: headers
];

Works

response = invokeurl
[
	url: "https://api.example.com/v1/orders"
	type: GET
	connection: "example_api"
];

Zoho docs: Connections

DLG041 Info

External side effects without an environment guard

In apps that use environments, development and stage share code with production. Guard live HTTP calls, emails and payments with thisapp.environment.type == "production" (or a config flag).

Example

Fails

response = invokeurl
[
	url: "https://payments.example.com/v1/capture"
	type: POST
	connection: "payments_api"
];

Works

if(thisapp.environment.type == "production")
{
	response = invokeurl
	[
		url: "https://payments.example.com/v1/capture"
		type: POST
		connection: "payments_api"
	];
}

Zoho docs: Environment attributes

DLG112 Warning

Hard-coded secret in code

Tokens, API keys, passwords, client secrets and secret webhook URLs must not be literals in Deluge (visible to every developer, exported in .ds files and backups, sent to AI tools). Use Connections or an admin-only encrypted settings field.

Example

Fails

headers = Map();
headers.put("Authorization", "Bearer 4f9c2e7a1b3d5f60a8c4e2d1");

Works

response = invokeurl
[
	url: "https://api.example.com/v1/charges"
	type: GET
	connection: "payments_api"
];
DLG127 Error

Secret placeholder would reach Creator unrehydrated

A ZENITH_SECRET_<hex8> placeholder in code bound for Creator must be restored from the vault for this component; otherwise Creator would store the placeholder instead of the secret.

Example

Fails

headers.put("Authorization", "Bearer ZENITH_SECRET_0a1b2c3d");

Works

response = invokeurl
[
	url: "https://api.example.com/v1/x"
	type: GET
	connection: "example_api"
];

Performance 3

DLG013 Warning

Nested loops over fetched records (O(n×m))

A for each over records inside another for each over records multiplies statements and fetches. Build a Map keyed by the join field, or fetch once with in and aggregate.

Example

Fails

for each order_rec in Orders[Status == "Open"]
{
	for each customer_rec in Customers[ID != 0]
	{
		if(customer_rec.ID == order_rec.Customer)
		{
			info customer_rec.Email;
		}
	}
}

Works

open_orders = Orders[Status == "Open"];
email_by_customer = Map();
for each customer_rec in Customers[ID in open_orders.Customer.ID.getAll()]
{
	email_by_customer.put(customer_rec.ID, customer_rec.Email);
}
for each order_rec in open_orders
{
	info email_by_customer.get(order_rec.Customer);
}

Zoho docs: Deluge limits

DLG037 Warning

HTTP, integration tasks or sendmail inside loops

Each invokeurl, zoho.* integration task or sendmail run consumes metered quota and up to 40 s; inside large loops it also risks the statement budget. Batch the request, send one digest, or enqueue per-item work.

Example

Fails

for each customer_rec in Customers[Tier == "Gold"]
{
	sendmail
	[
		from: zoho.adminuserid
		to: customer_rec.Email
		subject: "Offer"
		message: "Hello"
	]
}

Works

gold_emails = Customers[Tier == "Gold"].Email.getAll();
sendmail
[
	from: zoho.adminuserid
	to: zoho.adminuserid
	bcc: gold_emails
	subject: "Offer"
	message: "Hello"
]

Zoho docs: invokeurl task, Deluge limits

DLG038 Info

Fetching every record without a range

Form[ID != 0] (or ID > 0, ID != null) loads the whole form. Zoho advises fetching all records only when absolutely needed. Add criteria, an aggregate, or range.

Example

Fails

for each order_rec in Orders[ID != 0]
{
	total = total + order_rec.Total;
}

Works

total = Orders[Status == "Paid"].sum(Total);

Zoho docs: Fetch records

Error handling 2

DLG003 Info

throw (2026-08-25+): make sure it is handled deliberately

throw is supported since 2026-08-25 (text, a {"message","data"} map, or a caught exception). Uncaught exceptions propagate to callers and fail the run. Prefer result maps for reusable functions; if the project targets an older runtime, throw is a save error.

Example

Fails

map Orders.Submit(int order_id_param)
{
	throw "Order not ready";
}

Works

map Orders.Submit(int order_id_param)
{
	result = Map();
	result.put("success", false);
	result.put("message", "Order not ready");
	return result;
}

Zoho docs: throw statement

DLG039 Info

Empty catch block

An empty catch hides failures, especially in schedules nobody watches. Log e.message and set a status or return a failure result.

Example

Fails

try
{
	thisapp.Orders.Sync(order_id_param);
}
catch (e)
{
}

Works

try
{
	thisapp.Orders.Sync(order_id_param);
}
catch (e)
{
	info "[FAIL] sync " + order_id_param + ": " + e.message;
}

Logging 2

DLG014 Info

Logging whole payloads with info

info output is capped (500 KB per function, 50 KB in batch workflows) and visible to every developer. Log status, IDs, counts and a guarded preview instead of whole responses or maps.

Example

Fails

response = invokeurl
[
	url: "https://api.example.com/v1/orders"
	type: GET
	connection: "example_api"
];
info response;

Works

response = invokeurl
[
	url: "https://api.example.com/v1/orders"
	type: GET
	connection: "example_api"
];
response_text = response.toString();
info "orders response: " + response_text.length() + " chars";
info response_text.subString(0, min(response_text.length(), 1000));

Zoho docs: info

DLG040 Info

Pictographic emoji in info output

Creator's log viewer shows most pictographs (🔴 📊 💡 🚀 …) as '?'. Use ASCII tags ([OK], [FAIL], [WARN]) or basic symbols (✓ ✗ → •).

Example

Fails

info "🚀 sync started";

Works

info "[START] sync started";

Maintainability 2

DLG113 Info

Hard-coded record IDs

Long numeric record IDs in logic differ between environments and app copies and hide intent. Read them from config, a lookup, or a query by business key.

Example

Fails

manager_rec = Users_Directory[ID == 4123870000000215027];

Works

config = thisapp.App_Config.Get();
manager_rec = Users_Directory[ID == config.get("default_manager_id")];
DLG123 Info Checks your app's schema

New code depends on a component marked legacy

When the project marks forms or functions as legacy or deprecated, new code should not call or extend them without an explicit decision.

Example

Fails

thisapp.Legacy_Billing.Post_Invoice(invoice_id);

Works

thisapp.Billing.Post_Invoice(invoice_id);