The sys_attachment table deliberately has no foreign key constraints to any specific table — it's a generic attachment store. This means you must filter on both table_name and table_sys_id together. Filter on just table_sys_id alone and you'll get attachments from every table that happens to have a record with that same sys_id — a guaranteed data leak that's impossible to spot in testing but will surface in production.

When to use this

  • When you need attachment metadata (filename, size, creation date) for display in lists or reports
  • When validating attachment count limits or total size restrictions in Business Rules
  • When building custom attachment management workflows that need to process multiple files
  • When auditing or cleanup scripts need to identify orphaned or oversized attachments

When NOT to use this

  • Don't use this in client scripts — use GlideAjax to call a Script Include instead
  • Don't use this when you only need an attachment count — use GlideAggregate with addAggregate('COUNT')
  • Don't use this inside loops over other GlideRecords — you'll create N+1 query performance problems
  • Don't use this for downloading attachment content — use GlideSysAttachment.get() instead

Key behaviors and gotchas

  • The table_name field stores the exact table name, not the label — use 'incident' not 'Incident'
  • Both size_bytes and size_compressed are stored as strings — convert to integers for math operations
  • ACLs on sys_attachment are separate from the parent record — a user might see attachment metadata but not be able to download files
  • Deleted records leave orphaned attachments — the table_sys_id will point to a non-existent record
  • Extended table attachments store the base table name — incident attachments on u_custom_incident still show table_name='incident'
  • Domain separation applies — attachments in other domains won't appear unless you have cross-domain read access
⚠️

Never filter sys_attachment by table_sys_id alone — you'll get attachments from every table with matching sys_ids. Always include table_name in your query conditions.

Free Newsletter

Enjoying this? Get one deep-dive per week.

Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.

No spam · Unsubscribe anytime