zaproxy/zaproxy · warning · Exception

ascan.policy.warn.readonly

Error message

ascan.policy.warn.readonly

What it means

Read-only (built-in default) scan policies cannot be renamed; validateParam throws the localized 'ascan.policy.warn.readonly' message ('Policy is read-only') when the policy isReadOnly() and the name is left unchanged, blocking a save that would attempt to mutate it.

Source

Thrown at zap/src/main/java/org/zaproxy/zap/extension/ascan/PolicyAllCategoryPanel.java:572

        if (newName.length() == 0) {
            getPolicyName().requestFocusInWindow();
            throw new Exception(Constant.messages.getString("ascan.policy.warn.noname"));
        } else if (!extension.getPolicyManager().isLegalPolicyName(newName)) {
            getPolicyName().requestFocusInWindow();
            throw new Exception(
                    Constant.messages.getString(
                            "ascan.policy.warn.badname", PolicyManager.ILLEGAL_POLICY_NAME_CHRS));

        } else if (!newName.equals(currentName)) {
            // Name changed
            if (extension.getPolicyManager().getAllPolicyNames().stream()
                    .anyMatch(newName::equalsIgnoreCase)) {
                getPolicyName().requestFocusInWindow();
                throw new Exception(Constant.messages.getString("ascan.policy.warn.exists"));
            }
        }
        if (policy.isReadOnly() && newName.equals(currentName)) {
            throw new Exception(Constant.messages.getString("ascan.policy.warn.readonly"));
        }
    }

    @Override
    public void saveParam(Object obj) throws Exception {
        this.policy.setName(getPolicyName().getText());
        if (locked != null) {
            policy.setLocked(locked.isSelected());
        }
    }

    /**
     * This method initializes jScrollPane
     *
     * @return javax.swing.JScrollPane
     */
    private JScrollPane getJScrollPane() {
        if (jScrollPane == null) {

View on GitHub (pinned to 9d1970a436)

Solutions

  1. Duplicate the policy under a new name and modify the copy instead of the read-only default.
  2. Do not save read-only policies; cancel the dialog unless you actually renamed it.
  3. In code, check policy.isReadOnly() before invoking save/validation paths.

Example fix

// before
if (panel.getPolicy().isReadOnly()) panel.saveParam(panel.getPolicy()); // throws
// after
if (!panel.getPolicy().isReadOnly()) panel.saveParam(panel.getPolicy());
Defensive patterns

Strategy: validation

Validate before calling

if (policy.isReadOnly()) { /* duplicate first */
  ScanPolicy copy = new ScanPolicy(new File(dir, newName + ".policy"));
  copy.setName(newName); policyManager.savePolicy(copy); return;
}

Try / catch

try { panel.saveParam(obj); } catch (Exception e) { if (e.getMessage().startsWith("ascan.policy.warn.readonly")) { /* cancel or offer duplicate */ } }

Prevention

When it happens

Trigger: Opening a built-in/default policy in the policy dialog and pressing OK (or attempting save) without changing the name - the dialog tries to save a read-only policy.

Common situations: Browsing the Default Policy tab and clicking OK; scripts or add-ons programmatically validating a read-only policy via the panel; attempting to modify default policies shipped with ZAP.

Related errors


AI-assisted analysis of zaproxy/zaproxy@9d1970a436 (2026-09-05). Data as JSON: /api/errors/d78f18c4ed140547. Report an issue: GitHub.