hcengineering/platform · error · DeviceUnsupportedError

getDisplayMedia not supported

Error message

getDisplayMedia not supported

What it means

The mail service endpoint in services/mail/pod-mail/src/main.ts responds with HTTP 400 and { err: "'to' is missing" } when the send-mail request body lacks the 'to' recipient address. handleSendMail checks required fields in order (text/html, subject, to, from) and stops at the first missing one, so receiving this error means text/html and subject were present but 'to' was not.

Source

Thrown at desktop/src/ui/screenShare.ts:30

// See the License for the specific language governing permissions and
// limitations under the License.
//

import log from 'electron-log'
import love from '@hcengineering/love'
import { setCustomCreateScreenTracks } from '@hcengineering/love-resources'
import { showPopup } from '@hcengineering/ui'
import { Track, LocalTrack, LocalAudioTrack, LocalVideoTrack, ParticipantEvent, TrackInvalidError, ScreenShareCaptureOptions, DeviceUnsupportedError, ScreenSharePresets } from 'livekit-client'
import { ipcMainExposed } from './typesUtils'

export function defineGetDisplayMedia (): void {
  if (navigator?.mediaDevices === undefined) {
    console.warn('mediaDevices API not available')
    return
  }

  if (navigator.mediaDevices.getDisplayMedia === undefined) {
    throw new DeviceUnsupportedError('getDisplayMedia not supported')
  }

  navigator.mediaDevices.getDisplayMedia = async (opts?: DisplayMediaStreamOptions): Promise<MediaStream> => {
    if (opts === undefined) {
      throw new Error('opts must be provided')
    }

    const ipcMain = ipcMainExposed()
    const sources = await ipcMain.getScreenSources()

    const hasAccess = await ipcMain.getScreenAccess()
    if (!hasAccess) {
      log.error('No screen access granted')
      throw new Error('No screen access granted')
    }

    return await new Promise<MediaStream>((resolve, reject) => {
      let wasSelected = false

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Add a valid 'to' recipient address (string or array of addresses) to the request body.
  2. Filter upstream recipient lists to entries that actually have an email before calling the endpoint.
  3. Skip or queue records without recipients instead of calling the endpoint with an empty/undefined 'to'.
  4. Log the payload at the caller to confirm 'to' survives serialization.

Example fix

// before
const body = { from, subject, text, to: user.email } // user.email may be undefined
// after
if (!user.email) throw new Error(`User ${user.id} has no email`)
const body = { from, subject, text, to: user.email }
Defensive patterns

Strategy: validation

Validate before calling

if (!to || (Array.isArray(to) && to.length === 0)) {
  throw new Error('at least one recipient (to) is required before calling the mail endpoint')
}

Type guard

function hasRecipient(body: unknown): body is { to: string | string[]; [k: string]: unknown } {
  const t = (body as any)?.to
  return typeof t === 'string' ? t.length > 0 : Array.isArray(t) && t.length > 0
}

Try / catch

const res = await fetch(mailUrl, { method: 'POST', body })
if (res.status === 400) {
  const { err } = await res.json()
  if (err === "'to' is missing") {
    // skip/queue this record and log which entity had no recipient
  }
}

Prevention

When it happens

Trigger: POSTing to the mail endpoint with subject and a body (text or html) but no 'to' property in the JSON body, or 'to' serialized as null/undefined.

Common situations: Recipients list built from an optional upstream field (e.g. a user without an email); template-driven sends where the recipient placeholder was never filled; batch scripts iterating records with missing contact info.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/2d7ab8f69d63f113. Report an issue: GitHub.