halo-dev/halo · error · Error
Policy name is required
Error message
Policy name is required
What it means
Thrown in UploadFromUrl.vue's onSubmit before calling consoleApiClient.storage.attachment.externalTransferAttachment. The external-transfer API requires a policyName (the storage policy that will own the remote-fetched attachment). If the parent did not pass policyName (it defaults to undefined), the call is aborted with this guard to prevent sending an invalid uploadFromUrlRequest.
Source
Thrown at ui/console-src/modules/contents/attachments/components/UploadFromUrl.vue:37
}
);
const emit = defineEmits<{
(event: "uploaded", attachment: Attachment): void;
}>();
onMounted(() => {
setFocus("url");
});
const downloading = ref(false);
async function onSubmit({ url }: { url: string }) {
try {
downloading.value = true;
if (!props.policyName) {
throw new Error("Policy name is required");
}
const { data } =
await consoleApiClient.storage.attachment.externalTransferAttachment({
uploadFromUrlRequest: {
url: url,
policyName: props.policyName,
groupName: props.groupName,
},
});
Toast.success(
t("core.attachment.upload_modal.download_form.toast.success")
);
reset("url");
emit("uploaded", data);
} catch (error) {View on GitHub (pinned to d2f5165f9c)
Solutions
- Configure at least one storage policy (Attachments → Storage Policies) so the upload modal can pass a policyName.
- Ensure the parent component binds :policy-name from the active policy selector and that a default policy is selected when the modal opens.
- Disable the submit button until a policyName is present: :disabled="!policyName".
- If embedding UploadFromUrl in a custom view, pass policyName explicitly as a required value.
Example fix
// before
if (!props.policyName) {
throw new Error("Policy name is required");
}
// after — validate up front with a clear UX signal and avoid throw in submit
if (!props.policyName) {
Toast.warning(t("core.attachment.upload_modal.policy_required"));
return;
} Defensive patterns
Strategy: validation
Validate before calling
// Validate required props before calling the external-transfer API
function validateUploadFromUrl(policyName: string | undefined, url: string): string[] {
const errors: string[] = [];
if (!policyName || !policyName.trim()) errors.push("Policy name is required");
try { new URL(url); } catch { errors.push("A valid URL is required"); }
return errors;
} Type guard
function hasPolicyName(p: string | undefined): p is string {
return typeof p === "string" && p.trim().length > 0;
} Try / catch
async function onSubmit({ url }: { url: string }) {
try {
if (!hasPolicyName(props.policyName)) {
throw new Error("Policy name is required");
}
// ... externalTransferAttachment
} catch (error) {
Toast.error(error instanceof Error ? error.message : "Upload failed");
return error;
} finally { downloading.value = false; }
} Prevention
- Bind :policy-name from the parent's policy selector and ensure a default policy is selected on modal open.
- Disable the Download/Submit button until policyName is present.
- Configure at least one storage policy so policyName is never empty in normal use.
When it happens
Trigger: The UploadFromUrl component is rendered/mounted and the user submits a URL, but the parent (the upload modal) did not bind a policyName prop. externalTransferAttachment needs uploadFromUrlRequest.policyName; without it the backend would reject, so the client throws first. Also trips if the policy selector in the parent is empty (no storage policy configured or none selected).
Common situations: No storage policies are configured in the system, so the parent's policy selector is empty and policyName is undefined; the upload modal was opened in a context that skips policy selection; a refactor changed the prop binding; groupName is optional but policyName is required and the parent confused the two.
Related errors
- Attachment has no permalink
- No permission to upload attachment
- Please select a snapshot
- Please select two snapshots to compare
- File is required
AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14).
Data as JSON: /api/errors/21469ee153478d2f.
Report an issue: GitHub.