ratchetphp/Ratchet · error · UnexpectedValueException
Invalid site control set
Error message
Invalid site control set
What it means
FlashPolicy::setSiteControl() defines the <site-control permitted-cross-domain-policies="..."/> directive of the generated policy document. It validates the value via validateSiteControl() and throws UnexpectedValueException('Invalid site control set') for anything outside the Flash spec's accepted values. Only a fixed set of directives is legal: 'all', 'none', 'master-only', 'by-content-type', and 'by-ftp-filename'.
Solutions
- Use one of the five spec-valid values: 'all', 'none', 'master-only', 'by-content-type', 'by-ftp-filename'.
- If the intent is to restrict which domains may connect, do not change site-control — call addAllowedAccess() for each permitted domain instead.
- Whitelist/normalize the value in your config layer (strtolower plus in_array check) before passing it to setSiteControl.
- If unsure, omit setSiteControl; the default 'all' (permitted cross-domain policies everywhere) is applied by the constructor.
Example fix
// before
$fp->setSiteControl('allow-all');
// after
$fp->setSiteControl('all'); // or 'master-only', 'none', 'by-content-type', 'by-ftp-filename' Defensive patterns
Strategy: validation
Validate before calling
$allowed = ['all', 'none', 'master-only', 'by-content-type', 'by-ftp-filename'];
$value = strtolower(trim($permittedCrossDomainPolicies));
if (!in_array($value, $allowed, true)) {
throw new \InvalidArgumentException("permitted-cross-domain-policies must be one of: " . implode(', ', $allowed));
}
$fp->setSiteControl($value); Type guard
function isValidSiteControl($v): bool {
return in_array($v, ['all','none','master-only','by-content-type','by-ftp-filename'], true);
} Try / catch
try {
$fp->setSiteControl($directive);
} catch (\UnexpectedValueException $e) {
if ($e->getMessage() === 'Invalid site control set') {
error_log("Invalid permitted-cross-domain-policies directive: {$directive}");
} else { throw $e; }
} Prevention
- Keep a whitelist constant of the five valid directives and validate config against it.
- Remember site-control is a meta-policy, not a domain allow-list — use addAllowedAccess for domains.
- Normalize case/whitespace from environment variables before passing the directive.
- Prefer the default and omit setSiteControl unless you specifically need 'none' or 'master-only'.
When it happens
Trigger: Passing an arbitrary string like 'always', 'true', 'allow', or a custom policy name; leaving a config value blank or misspelling one of the five valid directives (e.g. 'Master-Only' with different casing if the validator is case-sensitive); calling setSiteControl with user-supplied input without whitelisting.
Common situations: Misunderstanding site-control as an allow-list (it is not; allowed domains go to addAllowedAccess); copying a meta-policy value from a different spec; config drift where the environment variable for the directive contains an unsupported option.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid domain
- Invalid Port
- $request can not be null
- All routes must implement Ratchet\Http\HttpServerInterface
- Argument #4 ($loop) expected…
AI-assisted analysis of ratchetphp/Ratchet@e621c6c40b (2026-09-16).
Data as JSON: /api/errors/aec3f0518b3a1675.
Report an issue: GitHub.
Appendix: source
Thrown at src/Ratchet/Server/FlashPolicy.php:98
public function clearAllowedAccess() {
$this->_access = array();
$this->_cacheValid = false;
return $this;
}
/**
* site-control defines the meta-policy for the current domain. A meta-policy specifies acceptable
* domain policy files other than the master policy file located in the target domain's root and named
* crossdomain.xml.
*
* @param string $permittedCrossDomainPolicies
* @throws \UnexpectedValueException
* @return FlashPolicy
*/
public function setSiteControl($permittedCrossDomainPolicies = 'all') {
if (!$this->validateSiteControl($permittedCrossDomainPolicies)) {
throw new \UnexpectedValueException('Invalid site control set');
}
$this->_siteControl = $permittedCrossDomainPolicies;
$this->_cacheValid = false;
return $this;
}
/**
* {@inheritdoc}
*/
public function onOpen(ConnectionInterface $conn) {
}
/**
* {@inheritdoc}
*/
public function onMessage(ConnectionInterface $from, $msg) {View on GitHub (pinned to e621c6c40b)